pretty-print-worker.js (418994B)
1 (function (factory) { 2 typeof define === 'function' && define.amd ? define(factory) : 3 factory(); 4 })((function () { 'use strict'; 5 6 (function() { 7 const env = {"NODE_ENV":"production"}; 8 try { 9 if (process) { 10 process.env = Object.assign({}, process.env); 11 Object.assign(process.env, env); 12 return; 13 } 14 } catch (e) {} // avoid ReferenceError: process is not defined 15 globalThis.process = { env:env }; 16 })(); 17 18 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 19 20 function getAugmentedNamespace(n) { 21 if (n.__esModule) return n; 22 var f = n.default; 23 if (typeof f == "function") { 24 var a = function a () { 25 if (this instanceof a) { 26 var args = [null]; 27 args.push.apply(args, arguments); 28 var Ctor = Function.bind.apply(f, args); 29 return new Ctor(); 30 } 31 return f.apply(this, arguments); 32 }; 33 a.prototype = f.prototype; 34 } else a = {}; 35 Object.defineProperty(a, '__esModule', {value: true}); 36 Object.keys(n).forEach(function (k) { 37 var d = Object.getOwnPropertyDescriptor(n, k); 38 Object.defineProperty(a, k, d.get ? d : { 39 enumerable: true, 40 get: function () { 41 return n[k]; 42 } 43 }); 44 }); 45 return a; 46 } 47 48 var sourceMap$1 = {}; 49 50 var sourceMapGenerator = {}; 51 52 var base64Vlq = {}; 53 54 var base64 = {}; 55 56 var hasRequiredBase64; 57 58 function requireBase64 () { 59 if (hasRequiredBase64) return base64; 60 hasRequiredBase64 = 1; 61 /* 62 * Copyright 2011 Mozilla Foundation and contributors 63 * Licensed under the New BSD license. See LICENSE or: 64 * http://opensource.org/licenses/BSD-3-Clause 65 */ 66 67 const intToCharMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""); 68 69 /** 70 * Encode an integer in the range of 0 to 63 to a single base 64 digit. 71 */ 72 base64.encode = function(number) { 73 if (0 <= number && number < intToCharMap.length) { 74 return intToCharMap[number]; 75 } 76 throw new TypeError("Must be between 0 and 63: " + number); 77 }; 78 return base64; 79 } 80 81 var hasRequiredBase64Vlq; 82 83 function requireBase64Vlq () { 84 if (hasRequiredBase64Vlq) return base64Vlq; 85 hasRequiredBase64Vlq = 1; 86 /* 87 * Copyright 2011 Mozilla Foundation and contributors 88 * Licensed under the New BSD license. See LICENSE or: 89 * http://opensource.org/licenses/BSD-3-Clause 90 * 91 * Based on the Base 64 VLQ implementation in Closure Compiler: 92 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java 93 * 94 * Copyright 2011 The Closure Compiler Authors. All rights reserved. 95 * Redistribution and use in source and binary forms, with or without 96 * modification, are permitted provided that the following conditions are 97 * met: 98 * 99 * * Redistributions of source code must retain the above copyright 100 * notice, this list of conditions and the following disclaimer. 101 * * Redistributions in binary form must reproduce the above 102 * copyright notice, this list of conditions and the following 103 * disclaimer in the documentation and/or other materials provided 104 * with the distribution. 105 * * Neither the name of Google Inc. nor the names of its 106 * contributors may be used to endorse or promote products derived 107 * from this software without specific prior written permission. 108 * 109 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 110 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 111 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 112 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 113 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 114 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 115 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 116 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 117 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 118 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 119 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 120 */ 121 122 const base64 = requireBase64(); 123 124 // A single base 64 digit can contain 6 bits of data. For the base 64 variable 125 // length quantities we use in the source map spec, the first bit is the sign, 126 // the next four bits are the actual value, and the 6th bit is the 127 // continuation bit. The continuation bit tells us whether there are more 128 // digits in this value following this digit. 129 // 130 // Continuation 131 // | Sign 132 // | | 133 // V V 134 // 101011 135 136 const VLQ_BASE_SHIFT = 5; 137 138 // binary: 100000 139 const VLQ_BASE = 1 << VLQ_BASE_SHIFT; 140 141 // binary: 011111 142 const VLQ_BASE_MASK = VLQ_BASE - 1; 143 144 // binary: 100000 145 const VLQ_CONTINUATION_BIT = VLQ_BASE; 146 147 /** 148 * Converts from a two-complement value to a value where the sign bit is 149 * placed in the least significant bit. For example, as decimals: 150 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) 151 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) 152 */ 153 function toVLQSigned(aValue) { 154 return aValue < 0 155 ? ((-aValue) << 1) + 1 156 : (aValue << 1) + 0; 157 } 158 159 /** 160 * Returns the base 64 VLQ encoded value. 161 */ 162 base64Vlq.encode = function base64VLQ_encode(aValue) { 163 let encoded = ""; 164 let digit; 165 166 let vlq = toVLQSigned(aValue); 167 168 do { 169 digit = vlq & VLQ_BASE_MASK; 170 vlq >>>= VLQ_BASE_SHIFT; 171 if (vlq > 0) { 172 // There are still more digits in this value, so we must make sure the 173 // continuation bit is marked. 174 digit |= VLQ_CONTINUATION_BIT; 175 } 176 encoded += base64.encode(digit); 177 } while (vlq > 0); 178 179 return encoded; 180 }; 181 return base64Vlq; 182 } 183 184 var util = {}; 185 186 var hasRequiredUtil; 187 188 function requireUtil () { 189 if (hasRequiredUtil) return util; 190 hasRequiredUtil = 1; 191 (function (exports) { 192 /* 193 * Copyright 2011 Mozilla Foundation and contributors 194 * Licensed under the New BSD license. See LICENSE or: 195 * http://opensource.org/licenses/BSD-3-Clause 196 */ 197 198 /** 199 * This is a helper function for getting values from parameter/options 200 * objects. 201 * 202 * @param args The object we are extracting values from 203 * @param name The name of the property we are getting. 204 * @param defaultValue An optional value to return if the property is missing 205 * from the object. If this is not specified and the property is missing, an 206 * error will be thrown. 207 */ 208 function getArg(aArgs, aName, aDefaultValue) { 209 if (aName in aArgs) { 210 return aArgs[aName]; 211 } else if (arguments.length === 3) { 212 return aDefaultValue; 213 } 214 throw new Error('"' + aName + '" is a required argument.'); 215 216 } 217 exports.getArg = getArg; 218 219 const urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/; 220 const dataUrlRegexp = /^data:.+\,.+$/; 221 222 function urlParse(aUrl) { 223 const match = aUrl.match(urlRegexp); 224 if (!match) { 225 return null; 226 } 227 return { 228 scheme: match[1], 229 auth: match[2], 230 host: match[3], 231 port: match[4], 232 path: match[5] 233 }; 234 } 235 exports.urlParse = urlParse; 236 237 function urlGenerate(aParsedUrl) { 238 let url = ""; 239 if (aParsedUrl.scheme) { 240 url += aParsedUrl.scheme + ":"; 241 } 242 url += "//"; 243 if (aParsedUrl.auth) { 244 url += aParsedUrl.auth + "@"; 245 } 246 if (aParsedUrl.host) { 247 url += aParsedUrl.host; 248 } 249 if (aParsedUrl.port) { 250 url += ":" + aParsedUrl.port; 251 } 252 if (aParsedUrl.path) { 253 url += aParsedUrl.path; 254 } 255 return url; 256 } 257 exports.urlGenerate = urlGenerate; 258 259 const MAX_CACHED_INPUTS = 32; 260 261 /** 262 * Takes some function `f(input) -> result` and returns a memoized version of 263 * `f`. 264 * 265 * We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The 266 * memoization is a dumb-simple, linear least-recently-used cache. 267 */ 268 function lruMemoize(f) { 269 const cache = []; 270 271 return function(input) { 272 for (let i = 0; i < cache.length; i++) { 273 if (cache[i].input === input) { 274 const temp = cache[0]; 275 cache[0] = cache[i]; 276 cache[i] = temp; 277 return cache[0].result; 278 } 279 } 280 281 const result = f(input); 282 283 cache.unshift({ 284 input, 285 result, 286 }); 287 288 if (cache.length > MAX_CACHED_INPUTS) { 289 cache.pop(); 290 } 291 292 return result; 293 }; 294 } 295 296 /** 297 * Normalizes a path, or the path portion of a URL: 298 * 299 * - Replaces consecutive slashes with one slash. 300 * - Removes unnecessary '.' parts. 301 * - Removes unnecessary '<dir>/..' parts. 302 * 303 * Based on code in the Node.js 'path' core module. 304 * 305 * @param aPath The path or url to normalize. 306 */ 307 const normalize = lruMemoize(function normalize(aPath) { 308 let path = aPath; 309 const url = urlParse(aPath); 310 if (url) { 311 if (!url.path) { 312 return aPath; 313 } 314 path = url.path; 315 } 316 const isAbsolute = exports.isAbsolute(path); 317 318 // Split the path into parts between `/` characters. This is much faster than 319 // using `.split(/\/+/g)`. 320 const parts = []; 321 let start = 0; 322 let i = 0; 323 while (true) { 324 start = i; 325 i = path.indexOf("/", start); 326 if (i === -1) { 327 parts.push(path.slice(start)); 328 break; 329 } else { 330 parts.push(path.slice(start, i)); 331 while (i < path.length && path[i] === "/") { 332 i++; 333 } 334 } 335 } 336 337 let up = 0; 338 for (i = parts.length - 1; i >= 0; i--) { 339 const part = parts[i]; 340 if (part === ".") { 341 parts.splice(i, 1); 342 } else if (part === "..") { 343 up++; 344 } else if (up > 0) { 345 if (part === "") { 346 // The first part is blank if the path is absolute. Trying to go 347 // above the root is a no-op. Therefore we can remove all '..' parts 348 // directly after the root. 349 parts.splice(i + 1, up); 350 up = 0; 351 } else { 352 parts.splice(i, 2); 353 up--; 354 } 355 } 356 } 357 path = parts.join("/"); 358 359 if (path === "") { 360 path = isAbsolute ? "/" : "."; 361 } 362 363 if (url) { 364 url.path = path; 365 return urlGenerate(url); 366 } 367 return path; 368 }); 369 exports.normalize = normalize; 370 371 /** 372 * Joins two paths/URLs. 373 * 374 * @param aRoot The root path or URL. 375 * @param aPath The path or URL to be joined with the root. 376 * 377 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a 378 * scheme-relative URL: Then the scheme of aRoot, if any, is prepended 379 * first. 380 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion 381 * is updated with the result and aRoot is returned. Otherwise the result 382 * is returned. 383 * - If aPath is absolute, the result is aPath. 384 * - Otherwise the two paths are joined with a slash. 385 * - Joining for example 'http://' and 'www.example.com' is also supported. 386 */ 387 function join(aRoot, aPath) { 388 if (aRoot === "") { 389 aRoot = "."; 390 } 391 if (aPath === "") { 392 aPath = "."; 393 } 394 const aPathUrl = urlParse(aPath); 395 const aRootUrl = urlParse(aRoot); 396 if (aRootUrl) { 397 aRoot = aRootUrl.path || "/"; 398 } 399 400 // `join(foo, '//www.example.org')` 401 if (aPathUrl && !aPathUrl.scheme) { 402 if (aRootUrl) { 403 aPathUrl.scheme = aRootUrl.scheme; 404 } 405 return urlGenerate(aPathUrl); 406 } 407 408 if (aPathUrl || aPath.match(dataUrlRegexp)) { 409 return aPath; 410 } 411 412 // `join('http://', 'www.example.com')` 413 if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { 414 aRootUrl.host = aPath; 415 return urlGenerate(aRootUrl); 416 } 417 418 const joined = aPath.charAt(0) === "/" 419 ? aPath 420 : normalize(aRoot.replace(/\/+$/, "") + "/" + aPath); 421 422 if (aRootUrl) { 423 aRootUrl.path = joined; 424 return urlGenerate(aRootUrl); 425 } 426 return joined; 427 } 428 exports.join = join; 429 430 exports.isAbsolute = function(aPath) { 431 return aPath.charAt(0) === "/" || urlRegexp.test(aPath); 432 }; 433 434 /** 435 * Make a path relative to a URL or another path. 436 * 437 * @param aRoot The root path or URL. 438 * @param aPath The path or URL to be made relative to aRoot. 439 */ 440 function relative(aRoot, aPath) { 441 if (aRoot === "") { 442 aRoot = "."; 443 } 444 445 aRoot = aRoot.replace(/\/$/, ""); 446 447 // It is possible for the path to be above the root. In this case, simply 448 // checking whether the root is a prefix of the path won't work. Instead, we 449 // need to remove components from the root one by one, until either we find 450 // a prefix that fits, or we run out of components to remove. 451 let level = 0; 452 while (aPath.indexOf(aRoot + "/") !== 0) { 453 const index = aRoot.lastIndexOf("/"); 454 if (index < 0) { 455 return aPath; 456 } 457 458 // If the only part of the root that is left is the scheme (i.e. http://, 459 // file:///, etc.), one or more slashes (/), or simply nothing at all, we 460 // have exhausted all components, so the path is not relative to the root. 461 aRoot = aRoot.slice(0, index); 462 if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { 463 return aPath; 464 } 465 466 ++level; 467 } 468 469 // Make sure we add a "../" for each component we removed from the root. 470 return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); 471 } 472 exports.relative = relative; 473 474 const supportsNullProto = (function() { 475 const obj = Object.create(null); 476 return !("__proto__" in obj); 477 }()); 478 479 function identity(s) { 480 return s; 481 } 482 483 /** 484 * Because behavior goes wacky when you set `__proto__` on objects, we 485 * have to prefix all the strings in our set with an arbitrary character. 486 * 487 * See https://github.com/mozilla/source-map/pull/31 and 488 * https://github.com/mozilla/source-map/issues/30 489 * 490 * @param String aStr 491 */ 492 function toSetString(aStr) { 493 if (isProtoString(aStr)) { 494 return "$" + aStr; 495 } 496 497 return aStr; 498 } 499 exports.toSetString = supportsNullProto ? identity : toSetString; 500 501 function fromSetString(aStr) { 502 if (isProtoString(aStr)) { 503 return aStr.slice(1); 504 } 505 506 return aStr; 507 } 508 exports.fromSetString = supportsNullProto ? identity : fromSetString; 509 510 function isProtoString(s) { 511 if (!s) { 512 return false; 513 } 514 515 const length = s.length; 516 517 if (length < 9 /* "__proto__".length */) { 518 return false; 519 } 520 521 /* eslint-disable no-multi-spaces */ 522 if (s.charCodeAt(length - 1) !== 95 /* '_' */ || 523 s.charCodeAt(length - 2) !== 95 /* '_' */ || 524 s.charCodeAt(length - 3) !== 111 /* 'o' */ || 525 s.charCodeAt(length - 4) !== 116 /* 't' */ || 526 s.charCodeAt(length - 5) !== 111 /* 'o' */ || 527 s.charCodeAt(length - 6) !== 114 /* 'r' */ || 528 s.charCodeAt(length - 7) !== 112 /* 'p' */ || 529 s.charCodeAt(length - 8) !== 95 /* '_' */ || 530 s.charCodeAt(length - 9) !== 95 /* '_' */) { 531 return false; 532 } 533 /* eslint-enable no-multi-spaces */ 534 535 for (let i = length - 10; i >= 0; i--) { 536 if (s.charCodeAt(i) !== 36 /* '$' */) { 537 return false; 538 } 539 } 540 541 return true; 542 } 543 544 /** 545 * Comparator between two mappings where the original positions are compared. 546 * 547 * Optionally pass in `true` as `onlyCompareGenerated` to consider two 548 * mappings with the same original source/line/column, but different generated 549 * line and column the same. Useful when searching for a mapping with a 550 * stubbed out mapping. 551 */ 552 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { 553 let cmp = strcmp(mappingA.source, mappingB.source); 554 if (cmp !== 0) { 555 return cmp; 556 } 557 558 cmp = mappingA.originalLine - mappingB.originalLine; 559 if (cmp !== 0) { 560 return cmp; 561 } 562 563 cmp = mappingA.originalColumn - mappingB.originalColumn; 564 if (cmp !== 0 || onlyCompareOriginal) { 565 return cmp; 566 } 567 568 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 569 if (cmp !== 0) { 570 return cmp; 571 } 572 573 cmp = mappingA.generatedLine - mappingB.generatedLine; 574 if (cmp !== 0) { 575 return cmp; 576 } 577 578 return strcmp(mappingA.name, mappingB.name); 579 } 580 exports.compareByOriginalPositions = compareByOriginalPositions; 581 582 /** 583 * Comparator between two mappings with deflated source and name indices where 584 * the generated positions are compared. 585 * 586 * Optionally pass in `true` as `onlyCompareGenerated` to consider two 587 * mappings with the same generated line and column, but different 588 * source/name/original line and column the same. Useful when searching for a 589 * mapping with a stubbed out mapping. 590 */ 591 function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { 592 let cmp = mappingA.generatedLine - mappingB.generatedLine; 593 if (cmp !== 0) { 594 return cmp; 595 } 596 597 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 598 if (cmp !== 0 || onlyCompareGenerated) { 599 return cmp; 600 } 601 602 cmp = strcmp(mappingA.source, mappingB.source); 603 if (cmp !== 0) { 604 return cmp; 605 } 606 607 cmp = mappingA.originalLine - mappingB.originalLine; 608 if (cmp !== 0) { 609 return cmp; 610 } 611 612 cmp = mappingA.originalColumn - mappingB.originalColumn; 613 if (cmp !== 0) { 614 return cmp; 615 } 616 617 return strcmp(mappingA.name, mappingB.name); 618 } 619 exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; 620 621 function strcmp(aStr1, aStr2) { 622 if (aStr1 === aStr2) { 623 return 0; 624 } 625 626 if (aStr1 === null) { 627 return 1; // aStr2 !== null 628 } 629 630 if (aStr2 === null) { 631 return -1; // aStr1 !== null 632 } 633 634 if (aStr1 > aStr2) { 635 return 1; 636 } 637 638 return -1; 639 } 640 641 /** 642 * Comparator between two mappings with inflated source and name strings where 643 * the generated positions are compared. 644 */ 645 function compareByGeneratedPositionsInflated(mappingA, mappingB) { 646 let cmp = mappingA.generatedLine - mappingB.generatedLine; 647 if (cmp !== 0) { 648 return cmp; 649 } 650 651 cmp = mappingA.generatedColumn - mappingB.generatedColumn; 652 if (cmp !== 0) { 653 return cmp; 654 } 655 656 cmp = strcmp(mappingA.source, mappingB.source); 657 if (cmp !== 0) { 658 return cmp; 659 } 660 661 cmp = mappingA.originalLine - mappingB.originalLine; 662 if (cmp !== 0) { 663 return cmp; 664 } 665 666 cmp = mappingA.originalColumn - mappingB.originalColumn; 667 if (cmp !== 0) { 668 return cmp; 669 } 670 671 return strcmp(mappingA.name, mappingB.name); 672 } 673 exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; 674 675 /** 676 * Strip any JSON XSSI avoidance prefix from the string (as documented 677 * in the source maps specification), and then parse the string as 678 * JSON. 679 */ 680 function parseSourceMapInput(str) { 681 return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, "")); 682 } 683 exports.parseSourceMapInput = parseSourceMapInput; 684 685 /** 686 * Compute the URL of a source given the the source root, the source's 687 * URL, and the source map's URL. 688 */ 689 function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) { 690 sourceURL = sourceURL || ""; 691 692 if (sourceRoot) { 693 // This follows what Chrome does. 694 if (sourceRoot[sourceRoot.length - 1] !== "/" && sourceURL[0] !== "/") { 695 sourceRoot += "/"; 696 } 697 // The spec says: 698 // Line 4: An optional source root, useful for relocating source 699 // files on a server or removing repeated values in the 700 // “sources” entry. This value is prepended to the individual 701 // entries in the “source” field. 702 sourceURL = sourceRoot + sourceURL; 703 } 704 705 // Historically, SourceMapConsumer did not take the sourceMapURL as 706 // a parameter. This mode is still somewhat supported, which is why 707 // this code block is conditional. However, it's preferable to pass 708 // the source map URL to SourceMapConsumer, so that this function 709 // can implement the source URL resolution algorithm as outlined in 710 // the spec. This block is basically the equivalent of: 711 // new URL(sourceURL, sourceMapURL).toString() 712 // ... except it avoids using URL, which wasn't available in the 713 // older releases of node still supported by this library. 714 // 715 // The spec says: 716 // If the sources are not absolute URLs after prepending of the 717 // “sourceRoot”, the sources are resolved relative to the 718 // SourceMap (like resolving script src in a html document). 719 if (sourceMapURL) { 720 const parsed = urlParse(sourceMapURL); 721 if (!parsed) { 722 throw new Error("sourceMapURL could not be parsed"); 723 } 724 if (parsed.path) { 725 // Strip the last path component, but keep the "/". 726 const index = parsed.path.lastIndexOf("/"); 727 if (index >= 0) { 728 parsed.path = parsed.path.substring(0, index + 1); 729 } 730 } 731 sourceURL = join(urlGenerate(parsed), sourceURL); 732 } 733 734 return normalize(sourceURL); 735 } 736 exports.computeSourceURL = computeSourceURL; 737 } (util)); 738 return util; 739 } 740 741 var arraySet = {}; 742 743 var hasRequiredArraySet; 744 745 function requireArraySet () { 746 if (hasRequiredArraySet) return arraySet; 747 hasRequiredArraySet = 1; 748 /* 749 * Copyright 2011 Mozilla Foundation and contributors 750 * Licensed under the New BSD license. See LICENSE or: 751 * http://opensource.org/licenses/BSD-3-Clause 752 */ 753 754 /** 755 * A data structure which is a combination of an array and a set. Adding a new 756 * member is O(1), testing for membership is O(1), and finding the index of an 757 * element is O(1). Removing elements from the set is not supported. Only 758 * strings are supported for membership. 759 */ 760 class ArraySet { 761 constructor() { 762 this._array = []; 763 this._set = new Map(); 764 } 765 766 /** 767 * Static method for creating ArraySet instances from an existing array. 768 */ 769 static fromArray(aArray, aAllowDuplicates) { 770 const set = new ArraySet(); 771 for (let i = 0, len = aArray.length; i < len; i++) { 772 set.add(aArray[i], aAllowDuplicates); 773 } 774 return set; 775 } 776 777 /** 778 * Return how many unique items are in this ArraySet. If duplicates have been 779 * added, than those do not count towards the size. 780 * 781 * @returns Number 782 */ 783 size() { 784 return this._set.size; 785 } 786 787 /** 788 * Add the given string to this set. 789 * 790 * @param String aStr 791 */ 792 add(aStr, aAllowDuplicates) { 793 const isDuplicate = this.has(aStr); 794 const idx = this._array.length; 795 if (!isDuplicate || aAllowDuplicates) { 796 this._array.push(aStr); 797 } 798 if (!isDuplicate) { 799 this._set.set(aStr, idx); 800 } 801 } 802 803 /** 804 * Is the given string a member of this set? 805 * 806 * @param String aStr 807 */ 808 has(aStr) { 809 return this._set.has(aStr); 810 } 811 812 /** 813 * What is the index of the given string in the array? 814 * 815 * @param String aStr 816 */ 817 indexOf(aStr) { 818 const idx = this._set.get(aStr); 819 if (idx >= 0) { 820 return idx; 821 } 822 throw new Error('"' + aStr + '" is not in the set.'); 823 } 824 825 /** 826 * What is the element at the given index? 827 * 828 * @param Number aIdx 829 */ 830 at(aIdx) { 831 if (aIdx >= 0 && aIdx < this._array.length) { 832 return this._array[aIdx]; 833 } 834 throw new Error("No element indexed by " + aIdx); 835 } 836 837 /** 838 * Returns the array representation of this set (which has the proper indices 839 * indicated by indexOf). Note that this is a copy of the internal array used 840 * for storing the members so that no one can mess with internal state. 841 */ 842 toArray() { 843 return this._array.slice(); 844 } 845 } 846 arraySet.ArraySet = ArraySet; 847 return arraySet; 848 } 849 850 var mappingList = {}; 851 852 var hasRequiredMappingList; 853 854 function requireMappingList () { 855 if (hasRequiredMappingList) return mappingList; 856 hasRequiredMappingList = 1; 857 /* 858 * Copyright 2014 Mozilla Foundation and contributors 859 * Licensed under the New BSD license. See LICENSE or: 860 * http://opensource.org/licenses/BSD-3-Clause 861 */ 862 863 const util = requireUtil(); 864 865 /** 866 * Determine whether mappingB is after mappingA with respect to generated 867 * position. 868 */ 869 function generatedPositionAfter(mappingA, mappingB) { 870 // Optimized for most common case 871 const lineA = mappingA.generatedLine; 872 const lineB = mappingB.generatedLine; 873 const columnA = mappingA.generatedColumn; 874 const columnB = mappingB.generatedColumn; 875 return lineB > lineA || lineB == lineA && columnB >= columnA || 876 util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; 877 } 878 879 /** 880 * A data structure to provide a sorted view of accumulated mappings in a 881 * performance conscious manner. It trades a negligible overhead in general 882 * case for a large speedup in case of mappings being added in order. 883 */ 884 class MappingList { 885 constructor() { 886 this._array = []; 887 this._sorted = true; 888 // Serves as infimum 889 this._last = {generatedLine: -1, generatedColumn: 0}; 890 } 891 892 /** 893 * Iterate through internal items. This method takes the same arguments that 894 * `Array.prototype.forEach` takes. 895 * 896 * NOTE: The order of the mappings is NOT guaranteed. 897 */ 898 unsortedForEach(aCallback, aThisArg) { 899 this._array.forEach(aCallback, aThisArg); 900 } 901 902 /** 903 * Add the given source mapping. 904 * 905 * @param Object aMapping 906 */ 907 add(aMapping) { 908 if (generatedPositionAfter(this._last, aMapping)) { 909 this._last = aMapping; 910 this._array.push(aMapping); 911 } else { 912 this._sorted = false; 913 this._array.push(aMapping); 914 } 915 } 916 917 /** 918 * Returns the flat, sorted array of mappings. The mappings are sorted by 919 * generated position. 920 * 921 * WARNING: This method returns internal data without copying, for 922 * performance. The return value must NOT be mutated, and should be treated as 923 * an immutable borrow. If you want to take ownership, you must make your own 924 * copy. 925 */ 926 toArray() { 927 if (!this._sorted) { 928 this._array.sort(util.compareByGeneratedPositionsInflated); 929 this._sorted = true; 930 } 931 return this._array; 932 } 933 } 934 935 mappingList.MappingList = MappingList; 936 return mappingList; 937 } 938 939 var hasRequiredSourceMapGenerator; 940 941 function requireSourceMapGenerator () { 942 if (hasRequiredSourceMapGenerator) return sourceMapGenerator; 943 hasRequiredSourceMapGenerator = 1; 944 /* 945 * Copyright 2011 Mozilla Foundation and contributors 946 * Licensed under the New BSD license. See LICENSE or: 947 * http://opensource.org/licenses/BSD-3-Clause 948 */ 949 950 const base64VLQ = requireBase64Vlq(); 951 const util = requireUtil(); 952 const ArraySet = requireArraySet().ArraySet; 953 const MappingList = requireMappingList().MappingList; 954 955 /** 956 * An instance of the SourceMapGenerator represents a source map which is 957 * being built incrementally. You may pass an object with the following 958 * properties: 959 * 960 * - file: The filename of the generated source. 961 * - sourceRoot: A root for all relative URLs in this source map. 962 */ 963 class SourceMapGenerator { 964 constructor(aArgs) { 965 if (!aArgs) { 966 aArgs = {}; 967 } 968 this._file = util.getArg(aArgs, "file", null); 969 this._sourceRoot = util.getArg(aArgs, "sourceRoot", null); 970 this._skipValidation = util.getArg(aArgs, "skipValidation", false); 971 this._sources = new ArraySet(); 972 this._names = new ArraySet(); 973 this._mappings = new MappingList(); 974 this._sourcesContents = null; 975 } 976 977 /** 978 * Creates a new SourceMapGenerator based on a SourceMapConsumer 979 * 980 * @param aSourceMapConsumer The SourceMap. 981 */ 982 static fromSourceMap(aSourceMapConsumer) { 983 const sourceRoot = aSourceMapConsumer.sourceRoot; 984 const generator = new SourceMapGenerator({ 985 file: aSourceMapConsumer.file, 986 sourceRoot 987 }); 988 aSourceMapConsumer.eachMapping(function(mapping) { 989 const newMapping = { 990 generated: { 991 line: mapping.generatedLine, 992 column: mapping.generatedColumn 993 } 994 }; 995 996 if (mapping.source != null) { 997 newMapping.source = mapping.source; 998 if (sourceRoot != null) { 999 newMapping.source = util.relative(sourceRoot, newMapping.source); 1000 } 1001 1002 newMapping.original = { 1003 line: mapping.originalLine, 1004 column: mapping.originalColumn 1005 }; 1006 1007 if (mapping.name != null) { 1008 newMapping.name = mapping.name; 1009 } 1010 } 1011 1012 generator.addMapping(newMapping); 1013 }); 1014 aSourceMapConsumer.sources.forEach(function(sourceFile) { 1015 let sourceRelative = sourceFile; 1016 if (sourceRoot !== null) { 1017 sourceRelative = util.relative(sourceRoot, sourceFile); 1018 } 1019 1020 if (!generator._sources.has(sourceRelative)) { 1021 generator._sources.add(sourceRelative); 1022 } 1023 1024 const content = aSourceMapConsumer.sourceContentFor(sourceFile); 1025 if (content != null) { 1026 generator.setSourceContent(sourceFile, content); 1027 } 1028 }); 1029 return generator; 1030 } 1031 1032 /** 1033 * Add a single mapping from original source line and column to the generated 1034 * source's line and column for this source map being created. The mapping 1035 * object should have the following properties: 1036 * 1037 * - generated: An object with the generated line and column positions. 1038 * - original: An object with the original line and column positions. 1039 * - source: The original source file (relative to the sourceRoot). 1040 * - name: An optional original token name for this mapping. 1041 */ 1042 addMapping(aArgs) { 1043 const generated = util.getArg(aArgs, "generated"); 1044 const original = util.getArg(aArgs, "original", null); 1045 let source = util.getArg(aArgs, "source", null); 1046 let name = util.getArg(aArgs, "name", null); 1047 1048 if (!this._skipValidation) { 1049 this._validateMapping(generated, original, source, name); 1050 } 1051 1052 if (source != null) { 1053 source = String(source); 1054 if (!this._sources.has(source)) { 1055 this._sources.add(source); 1056 } 1057 } 1058 1059 if (name != null) { 1060 name = String(name); 1061 if (!this._names.has(name)) { 1062 this._names.add(name); 1063 } 1064 } 1065 1066 this._mappings.add({ 1067 generatedLine: generated.line, 1068 generatedColumn: generated.column, 1069 originalLine: original != null && original.line, 1070 originalColumn: original != null && original.column, 1071 source, 1072 name 1073 }); 1074 } 1075 1076 /** 1077 * Set the source content for a source file. 1078 */ 1079 setSourceContent(aSourceFile, aSourceContent) { 1080 let source = aSourceFile; 1081 if (this._sourceRoot != null) { 1082 source = util.relative(this._sourceRoot, source); 1083 } 1084 1085 if (aSourceContent != null) { 1086 // Add the source content to the _sourcesContents map. 1087 // Create a new _sourcesContents map if the property is null. 1088 if (!this._sourcesContents) { 1089 this._sourcesContents = Object.create(null); 1090 } 1091 this._sourcesContents[util.toSetString(source)] = aSourceContent; 1092 } else if (this._sourcesContents) { 1093 // Remove the source file from the _sourcesContents map. 1094 // If the _sourcesContents map is empty, set the property to null. 1095 delete this._sourcesContents[util.toSetString(source)]; 1096 if (Object.keys(this._sourcesContents).length === 0) { 1097 this._sourcesContents = null; 1098 } 1099 } 1100 } 1101 1102 /** 1103 * Applies the mappings of a sub-source-map for a specific source file to the 1104 * source map being generated. Each mapping to the supplied source file is 1105 * rewritten using the supplied source map. Note: The resolution for the 1106 * resulting mappings is the minimium of this map and the supplied map. 1107 * 1108 * @param aSourceMapConsumer The source map to be applied. 1109 * @param aSourceFile Optional. The filename of the source file. 1110 * If omitted, SourceMapConsumer's file property will be used. 1111 * @param aSourceMapPath Optional. The dirname of the path to the source map 1112 * to be applied. If relative, it is relative to the SourceMapConsumer. 1113 * This parameter is needed when the two source maps aren't in the same 1114 * directory, and the source map to be applied contains relative source 1115 * paths. If so, those relative source paths need to be rewritten 1116 * relative to the SourceMapGenerator. 1117 */ 1118 applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { 1119 let sourceFile = aSourceFile; 1120 // If aSourceFile is omitted, we will use the file property of the SourceMap 1121 if (aSourceFile == null) { 1122 if (aSourceMapConsumer.file == null) { 1123 throw new Error( 1124 "SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, " + 1125 'or the source map\'s "file" property. Both were omitted.' 1126 ); 1127 } 1128 sourceFile = aSourceMapConsumer.file; 1129 } 1130 const sourceRoot = this._sourceRoot; 1131 // Make "sourceFile" relative if an absolute Url is passed. 1132 if (sourceRoot != null) { 1133 sourceFile = util.relative(sourceRoot, sourceFile); 1134 } 1135 // Applying the SourceMap can add and remove items from the sources and 1136 // the names array. 1137 const newSources = this._mappings.toArray().length > 0 1138 ? new ArraySet() 1139 : this._sources; 1140 const newNames = new ArraySet(); 1141 1142 // Find mappings for the "sourceFile" 1143 this._mappings.unsortedForEach(function(mapping) { 1144 if (mapping.source === sourceFile && mapping.originalLine != null) { 1145 // Check if it can be mapped by the source map, then update the mapping. 1146 const original = aSourceMapConsumer.originalPositionFor({ 1147 line: mapping.originalLine, 1148 column: mapping.originalColumn 1149 }); 1150 if (original.source != null) { 1151 // Copy mapping 1152 mapping.source = original.source; 1153 if (aSourceMapPath != null) { 1154 mapping.source = util.join(aSourceMapPath, mapping.source); 1155 } 1156 if (sourceRoot != null) { 1157 mapping.source = util.relative(sourceRoot, mapping.source); 1158 } 1159 mapping.originalLine = original.line; 1160 mapping.originalColumn = original.column; 1161 if (original.name != null) { 1162 mapping.name = original.name; 1163 } 1164 } 1165 } 1166 1167 const source = mapping.source; 1168 if (source != null && !newSources.has(source)) { 1169 newSources.add(source); 1170 } 1171 1172 const name = mapping.name; 1173 if (name != null && !newNames.has(name)) { 1174 newNames.add(name); 1175 } 1176 1177 }, this); 1178 this._sources = newSources; 1179 this._names = newNames; 1180 1181 // Copy sourcesContents of applied map. 1182 aSourceMapConsumer.sources.forEach(function(srcFile) { 1183 const content = aSourceMapConsumer.sourceContentFor(srcFile); 1184 if (content != null) { 1185 if (aSourceMapPath != null) { 1186 srcFile = util.join(aSourceMapPath, srcFile); 1187 } 1188 if (sourceRoot != null) { 1189 srcFile = util.relative(sourceRoot, srcFile); 1190 } 1191 this.setSourceContent(srcFile, content); 1192 } 1193 }, this); 1194 } 1195 1196 /** 1197 * A mapping can have one of the three levels of data: 1198 * 1199 * 1. Just the generated position. 1200 * 2. The Generated position, original position, and original source. 1201 * 3. Generated and original position, original source, as well as a name 1202 * token. 1203 * 1204 * To maintain consistency, we validate that any new mapping being added falls 1205 * in to one of these categories. 1206 */ 1207 _validateMapping(aGenerated, aOriginal, aSource, aName) { 1208 // When aOriginal is truthy but has empty values for .line and .column, 1209 // it is most likely a programmer error. In this case we throw a very 1210 // specific error message to try to guide them the right way. 1211 // For example: https://github.com/Polymer/polymer-bundler/pull/519 1212 if (aOriginal && typeof aOriginal.line !== "number" && typeof aOriginal.column !== "number") { 1213 throw new Error( 1214 "original.line and original.column are not numbers -- you probably meant to omit " + 1215 "the original mapping entirely and only map the generated position. If so, pass " + 1216 "null for the original mapping instead of an object with empty or null values." 1217 ); 1218 } 1219 1220 if (aGenerated && "line" in aGenerated && "column" in aGenerated 1221 && aGenerated.line > 0 && aGenerated.column >= 0 1222 && !aOriginal && !aSource && !aName) ; else if (aGenerated && "line" in aGenerated && "column" in aGenerated 1223 && aOriginal && "line" in aOriginal && "column" in aOriginal 1224 && aGenerated.line > 0 && aGenerated.column >= 0 1225 && aOriginal.line > 0 && aOriginal.column >= 0 1226 && aSource) ; else { 1227 throw new Error("Invalid mapping: " + JSON.stringify({ 1228 generated: aGenerated, 1229 source: aSource, 1230 original: aOriginal, 1231 name: aName 1232 })); 1233 } 1234 } 1235 1236 /** 1237 * Serialize the accumulated mappings in to the stream of base 64 VLQs 1238 * specified by the source map format. 1239 */ 1240 _serializeMappings() { 1241 let previousGeneratedColumn = 0; 1242 let previousGeneratedLine = 1; 1243 let previousOriginalColumn = 0; 1244 let previousOriginalLine = 0; 1245 let previousName = 0; 1246 let previousSource = 0; 1247 let result = ""; 1248 let next; 1249 let mapping; 1250 let nameIdx; 1251 let sourceIdx; 1252 1253 const mappings = this._mappings.toArray(); 1254 for (let i = 0, len = mappings.length; i < len; i++) { 1255 mapping = mappings[i]; 1256 next = ""; 1257 1258 if (mapping.generatedLine !== previousGeneratedLine) { 1259 previousGeneratedColumn = 0; 1260 while (mapping.generatedLine !== previousGeneratedLine) { 1261 next += ";"; 1262 previousGeneratedLine++; 1263 } 1264 } else if (i > 0) { 1265 if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { 1266 continue; 1267 } 1268 next += ","; 1269 } 1270 1271 next += base64VLQ.encode(mapping.generatedColumn 1272 - previousGeneratedColumn); 1273 previousGeneratedColumn = mapping.generatedColumn; 1274 1275 if (mapping.source != null) { 1276 sourceIdx = this._sources.indexOf(mapping.source); 1277 next += base64VLQ.encode(sourceIdx - previousSource); 1278 previousSource = sourceIdx; 1279 1280 // lines are stored 0-based in SourceMap spec version 3 1281 next += base64VLQ.encode(mapping.originalLine - 1 1282 - previousOriginalLine); 1283 previousOriginalLine = mapping.originalLine - 1; 1284 1285 next += base64VLQ.encode(mapping.originalColumn 1286 - previousOriginalColumn); 1287 previousOriginalColumn = mapping.originalColumn; 1288 1289 if (mapping.name != null) { 1290 nameIdx = this._names.indexOf(mapping.name); 1291 next += base64VLQ.encode(nameIdx - previousName); 1292 previousName = nameIdx; 1293 } 1294 } 1295 1296 result += next; 1297 } 1298 1299 return result; 1300 } 1301 1302 _generateSourcesContent(aSources, aSourceRoot) { 1303 return aSources.map(function(source) { 1304 if (!this._sourcesContents) { 1305 return null; 1306 } 1307 if (aSourceRoot != null) { 1308 source = util.relative(aSourceRoot, source); 1309 } 1310 const key = util.toSetString(source); 1311 return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) 1312 ? this._sourcesContents[key] 1313 : null; 1314 }, this); 1315 } 1316 1317 /** 1318 * Externalize the source map. 1319 */ 1320 toJSON() { 1321 const map = { 1322 version: this._version, 1323 sources: this._sources.toArray(), 1324 names: this._names.toArray(), 1325 mappings: this._serializeMappings() 1326 }; 1327 if (this._file != null) { 1328 map.file = this._file; 1329 } 1330 if (this._sourceRoot != null) { 1331 map.sourceRoot = this._sourceRoot; 1332 } 1333 if (this._sourcesContents) { 1334 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); 1335 } 1336 1337 return map; 1338 } 1339 1340 /** 1341 * Render the source map being generated to a string. 1342 */ 1343 toString() { 1344 return JSON.stringify(this.toJSON()); 1345 } 1346 } 1347 1348 SourceMapGenerator.prototype._version = 3; 1349 sourceMapGenerator.SourceMapGenerator = SourceMapGenerator; 1350 return sourceMapGenerator; 1351 } 1352 1353 var sourceMapConsumer = {}; 1354 1355 var binarySearch = {}; 1356 1357 var hasRequiredBinarySearch; 1358 1359 function requireBinarySearch () { 1360 if (hasRequiredBinarySearch) return binarySearch; 1361 hasRequiredBinarySearch = 1; 1362 (function (exports) { 1363 /* 1364 * Copyright 2011 Mozilla Foundation and contributors 1365 * Licensed under the New BSD license. See LICENSE or: 1366 * http://opensource.org/licenses/BSD-3-Clause 1367 */ 1368 1369 exports.GREATEST_LOWER_BOUND = 1; 1370 exports.LEAST_UPPER_BOUND = 2; 1371 1372 /** 1373 * Recursive implementation of binary search. 1374 * 1375 * @param aLow Indices here and lower do not contain the needle. 1376 * @param aHigh Indices here and higher do not contain the needle. 1377 * @param aNeedle The element being searched for. 1378 * @param aHaystack The non-empty array being searched. 1379 * @param aCompare Function which takes two elements and returns -1, 0, or 1. 1380 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or 1381 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the 1382 * closest element that is smaller than or greater than the one we are 1383 * searching for, respectively, if the exact element cannot be found. 1384 */ 1385 function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { 1386 // This function terminates when one of the following is true: 1387 // 1388 // 1. We find the exact element we are looking for. 1389 // 1390 // 2. We did not find the exact element, but we can return the index of 1391 // the next-closest element. 1392 // 1393 // 3. We did not find the exact element, and there is no next-closest 1394 // element than the one we are searching for, so we return -1. 1395 const mid = Math.floor((aHigh - aLow) / 2) + aLow; 1396 const cmp = aCompare(aNeedle, aHaystack[mid], true); 1397 if (cmp === 0) { 1398 // Found the element we are looking for. 1399 return mid; 1400 } else if (cmp > 0) { 1401 // Our needle is greater than aHaystack[mid]. 1402 if (aHigh - mid > 1) { 1403 // The element is in the upper half. 1404 return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); 1405 } 1406 1407 // The exact needle element was not found in this haystack. Determine if 1408 // we are in termination case (3) or (2) and return the appropriate thing. 1409 if (aBias == exports.LEAST_UPPER_BOUND) { 1410 return aHigh < aHaystack.length ? aHigh : -1; 1411 } 1412 return mid; 1413 } 1414 1415 // Our needle is less than aHaystack[mid]. 1416 if (mid - aLow > 1) { 1417 // The element is in the lower half. 1418 return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); 1419 } 1420 1421 // we are in termination case (3) or (2) and return the appropriate thing. 1422 if (aBias == exports.LEAST_UPPER_BOUND) { 1423 return mid; 1424 } 1425 return aLow < 0 ? -1 : aLow; 1426 } 1427 1428 /** 1429 * This is an implementation of binary search which will always try and return 1430 * the index of the closest element if there is no exact hit. This is because 1431 * mappings between original and generated line/col pairs are single points, 1432 * and there is an implicit region between each of them, so a miss just means 1433 * that you aren't on the very start of a region. 1434 * 1435 * @param aNeedle The element you are looking for. 1436 * @param aHaystack The array that is being searched. 1437 * @param aCompare A function which takes the needle and an element in the 1438 * array and returns -1, 0, or 1 depending on whether the needle is less 1439 * than, equal to, or greater than the element, respectively. 1440 * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or 1441 * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the 1442 * closest element that is smaller than or greater than the one we are 1443 * searching for, respectively, if the exact element cannot be found. 1444 * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. 1445 */ 1446 exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { 1447 if (aHaystack.length === 0) { 1448 return -1; 1449 } 1450 1451 let index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, 1452 aCompare, aBias || exports.GREATEST_LOWER_BOUND); 1453 if (index < 0) { 1454 return -1; 1455 } 1456 1457 // We have found either the exact element, or the next-closest element than 1458 // the one we are searching for. However, there may be more than one such 1459 // element. Make sure we always return the smallest of these. 1460 while (index - 1 >= 0) { 1461 if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { 1462 break; 1463 } 1464 --index; 1465 } 1466 1467 return index; 1468 }; 1469 } (binarySearch)); 1470 return binarySearch; 1471 } 1472 1473 var readWasm = {exports: {}}; 1474 1475 var empty = {}; 1476 1477 var empty$1 = /*#__PURE__*/Object.freeze({ 1478 __proto__: null, 1479 default: empty 1480 }); 1481 1482 var require$$0 = /*@__PURE__*/getAugmentedNamespace(empty$1); 1483 1484 // Copyright Joyent, Inc. and other Node contributors. 1485 // 1486 // Permission is hereby granted, free of charge, to any person obtaining a 1487 // copy of this software and associated documentation files (the 1488 // "Software"), to deal in the Software without restriction, including 1489 // without limitation the rights to use, copy, modify, merge, publish, 1490 // distribute, sublicense, and/or sell copies of the Software, and to permit 1491 // persons to whom the Software is furnished to do so, subject to the 1492 // following conditions: 1493 // 1494 // The above copyright notice and this permission notice shall be included 1495 // in all copies or substantial portions of the Software. 1496 // 1497 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1498 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1499 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 1500 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 1501 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 1502 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 1503 // USE OR OTHER DEALINGS IN THE SOFTWARE. 1504 1505 // resolves . and .. elements in a path array with directory names there 1506 // must be no slashes, empty elements, or device names (c:\) in the array 1507 // (so also no leading and trailing slashes - it does not distinguish 1508 // relative and absolute paths) 1509 function normalizeArray(parts, allowAboveRoot) { 1510 // if the path tries to go above the root, `up` ends up > 0 1511 var up = 0; 1512 for (var i = parts.length - 1; i >= 0; i--) { 1513 var last = parts[i]; 1514 if (last === '.') { 1515 parts.splice(i, 1); 1516 } else if (last === '..') { 1517 parts.splice(i, 1); 1518 up++; 1519 } else if (up) { 1520 parts.splice(i, 1); 1521 up--; 1522 } 1523 } 1524 1525 // if the path is allowed to go above the root, restore leading ..s 1526 if (allowAboveRoot) { 1527 for (; up--; up) { 1528 parts.unshift('..'); 1529 } 1530 } 1531 1532 return parts; 1533 } 1534 1535 // Split a filename into [root, dir, basename, ext], unix version 1536 // 'root' is just a slash, or nothing. 1537 var splitPathRe = 1538 /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; 1539 var splitPath = function(filename) { 1540 return splitPathRe.exec(filename).slice(1); 1541 }; 1542 1543 // path.resolve([from ...], to) 1544 // posix version 1545 function resolve() { 1546 var resolvedPath = '', 1547 resolvedAbsolute = false; 1548 1549 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { 1550 var path = (i >= 0) ? arguments[i] : '/'; 1551 1552 // Skip empty and invalid entries 1553 if (typeof path !== 'string') { 1554 throw new TypeError('Arguments to path.resolve must be strings'); 1555 } else if (!path) { 1556 continue; 1557 } 1558 1559 resolvedPath = path + '/' + resolvedPath; 1560 resolvedAbsolute = path.charAt(0) === '/'; 1561 } 1562 1563 // At this point the path should be resolved to a full absolute path, but 1564 // handle relative paths to be safe (might happen when process.cwd() fails) 1565 1566 // Normalize the path 1567 resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { 1568 return !!p; 1569 }), !resolvedAbsolute).join('/'); 1570 1571 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; 1572 } 1573 // path.normalize(path) 1574 // posix version 1575 function normalize(path) { 1576 var isPathAbsolute = isAbsolute(path), 1577 trailingSlash = substr(path, -1) === '/'; 1578 1579 // Normalize the path 1580 path = normalizeArray(filter(path.split('/'), function(p) { 1581 return !!p; 1582 }), !isPathAbsolute).join('/'); 1583 1584 if (!path && !isPathAbsolute) { 1585 path = '.'; 1586 } 1587 if (path && trailingSlash) { 1588 path += '/'; 1589 } 1590 1591 return (isPathAbsolute ? '/' : '') + path; 1592 } 1593 // posix version 1594 function isAbsolute(path) { 1595 return path.charAt(0) === '/'; 1596 } 1597 1598 // posix version 1599 function join() { 1600 var paths = Array.prototype.slice.call(arguments, 0); 1601 return normalize(filter(paths, function(p, index) { 1602 if (typeof p !== 'string') { 1603 throw new TypeError('Arguments to path.join must be strings'); 1604 } 1605 return p; 1606 }).join('/')); 1607 } 1608 1609 1610 // path.relative(from, to) 1611 // posix version 1612 function relative(from, to) { 1613 from = resolve(from).substr(1); 1614 to = resolve(to).substr(1); 1615 1616 function trim(arr) { 1617 var start = 0; 1618 for (; start < arr.length; start++) { 1619 if (arr[start] !== '') break; 1620 } 1621 1622 var end = arr.length - 1; 1623 for (; end >= 0; end--) { 1624 if (arr[end] !== '') break; 1625 } 1626 1627 if (start > end) return []; 1628 return arr.slice(start, end - start + 1); 1629 } 1630 1631 var fromParts = trim(from.split('/')); 1632 var toParts = trim(to.split('/')); 1633 1634 var length = Math.min(fromParts.length, toParts.length); 1635 var samePartsLength = length; 1636 for (var i = 0; i < length; i++) { 1637 if (fromParts[i] !== toParts[i]) { 1638 samePartsLength = i; 1639 break; 1640 } 1641 } 1642 1643 var outputParts = []; 1644 for (var i = samePartsLength; i < fromParts.length; i++) { 1645 outputParts.push('..'); 1646 } 1647 1648 outputParts = outputParts.concat(toParts.slice(samePartsLength)); 1649 1650 return outputParts.join('/'); 1651 } 1652 1653 var sep = '/'; 1654 var delimiter = ':'; 1655 1656 function dirname(path) { 1657 var result = splitPath(path), 1658 root = result[0], 1659 dir = result[1]; 1660 1661 if (!root && !dir) { 1662 // No dirname whatsoever 1663 return '.'; 1664 } 1665 1666 if (dir) { 1667 // It has a dirname, strip trailing slash 1668 dir = dir.substr(0, dir.length - 1); 1669 } 1670 1671 return root + dir; 1672 } 1673 1674 function basename(path, ext) { 1675 var f = splitPath(path)[2]; 1676 // TODO: make this comparison case-insensitive on windows? 1677 if (ext && f.substr(-1 * ext.length) === ext) { 1678 f = f.substr(0, f.length - ext.length); 1679 } 1680 return f; 1681 } 1682 1683 1684 function extname(path) { 1685 return splitPath(path)[3]; 1686 } 1687 var path = { 1688 extname: extname, 1689 basename: basename, 1690 dirname: dirname, 1691 sep: sep, 1692 delimiter: delimiter, 1693 relative: relative, 1694 join: join, 1695 isAbsolute: isAbsolute, 1696 normalize: normalize, 1697 resolve: resolve 1698 }; 1699 function filter (xs, f) { 1700 if (xs.filter) return xs.filter(f); 1701 var res = []; 1702 for (var i = 0; i < xs.length; i++) { 1703 if (f(xs[i], i, xs)) res.push(xs[i]); 1704 } 1705 return res; 1706 } 1707 1708 // String.prototype.substr - negative index don't work in IE8 1709 var substr = 'ab'.substr(-1) === 'b' ? 1710 function (str, start, len) { return str.substr(start, len) } : 1711 function (str, start, len) { 1712 if (start < 0) start = str.length + start; 1713 return str.substr(start, len); 1714 } 1715 ; 1716 1717 var path$1 = /*#__PURE__*/Object.freeze({ 1718 __proto__: null, 1719 basename: basename, 1720 default: path, 1721 delimiter: delimiter, 1722 dirname: dirname, 1723 extname: extname, 1724 isAbsolute: isAbsolute, 1725 join: join, 1726 normalize: normalize, 1727 relative: relative, 1728 resolve: resolve, 1729 sep: sep 1730 }); 1731 1732 var require$$1 = /*@__PURE__*/getAugmentedNamespace(path$1); 1733 1734 var hasRequiredReadWasm; 1735 1736 function requireReadWasm () { 1737 if (hasRequiredReadWasm) return readWasm.exports; 1738 hasRequiredReadWasm = 1; 1739 const isBrowserEnvironment = (function() { 1740 // eslint-disable-next-line no-undef 1741 return (typeof window !== "undefined") && (this === window); 1742 }).call(); 1743 1744 if (isBrowserEnvironment) { 1745 // Web version of reading a wasm file into an array buffer. 1746 1747 let mappingsWasm = null; 1748 1749 readWasm.exports = function readWasm() { 1750 if (typeof mappingsWasm === "string") { 1751 return fetch(mappingsWasm) 1752 .then(response => response.arrayBuffer()); 1753 } 1754 if (mappingsWasm instanceof ArrayBuffer) { 1755 return Promise.resolve(mappingsWasm); 1756 } 1757 throw new Error("You must provide the string URL or ArrayBuffer contents " + 1758 "of lib/mappings.wasm by calling " + 1759 "SourceMapConsumer.initialize({ 'lib/mappings.wasm': ... }) " + 1760 "before using SourceMapConsumer"); 1761 }; 1762 1763 readWasm.exports.initialize = input => mappingsWasm = input; 1764 } else { 1765 // Node version of reading a wasm file into an array buffer. 1766 const fs = require$$0; 1767 const path = require$$1; 1768 1769 readWasm.exports = function readWasm() { 1770 return new Promise((resolve, reject) => { 1771 const wasmPath = path.join(__dirname, "mappings.wasm"); 1772 fs.readFile(wasmPath, null, (error, data) => { 1773 if (error) { 1774 reject(error); 1775 return; 1776 } 1777 1778 resolve(data.buffer); 1779 }); 1780 }); 1781 }; 1782 1783 readWasm.exports.initialize = _ => { 1784 console.debug("SourceMapConsumer.initialize is a no-op when running in node.js"); 1785 }; 1786 } 1787 return readWasm.exports; 1788 } 1789 1790 var wasm; 1791 var hasRequiredWasm; 1792 1793 function requireWasm () { 1794 if (hasRequiredWasm) return wasm; 1795 hasRequiredWasm = 1; 1796 const readWasm = requireReadWasm(); 1797 1798 /** 1799 * Provide the JIT with a nice shape / hidden class. 1800 */ 1801 function Mapping() { 1802 this.generatedLine = 0; 1803 this.generatedColumn = 0; 1804 this.lastGeneratedColumn = null; 1805 this.source = null; 1806 this.originalLine = null; 1807 this.originalColumn = null; 1808 this.name = null; 1809 } 1810 1811 let cachedWasm = null; 1812 1813 wasm = function wasm() { 1814 if (cachedWasm) { 1815 return cachedWasm; 1816 } 1817 1818 const callbackStack = []; 1819 1820 cachedWasm = readWasm().then(buffer => { 1821 return WebAssembly.instantiate(buffer, { 1822 env: { 1823 mapping_callback( 1824 generatedLine, 1825 generatedColumn, 1826 1827 hasLastGeneratedColumn, 1828 lastGeneratedColumn, 1829 1830 hasOriginal, 1831 source, 1832 originalLine, 1833 originalColumn, 1834 1835 hasName, 1836 name 1837 ) { 1838 const mapping = new Mapping(); 1839 // JS uses 1-based line numbers, wasm uses 0-based. 1840 mapping.generatedLine = generatedLine + 1; 1841 mapping.generatedColumn = generatedColumn; 1842 1843 if (hasLastGeneratedColumn) { 1844 // JS uses inclusive last generated column, wasm uses exclusive. 1845 mapping.lastGeneratedColumn = lastGeneratedColumn - 1; 1846 } 1847 1848 if (hasOriginal) { 1849 mapping.source = source; 1850 // JS uses 1-based line numbers, wasm uses 0-based. 1851 mapping.originalLine = originalLine + 1; 1852 mapping.originalColumn = originalColumn; 1853 1854 if (hasName) { 1855 mapping.name = name; 1856 } 1857 } 1858 1859 callbackStack[callbackStack.length - 1](mapping); 1860 }, 1861 1862 start_all_generated_locations_for() { console.time("all_generated_locations_for"); }, 1863 end_all_generated_locations_for() { console.timeEnd("all_generated_locations_for"); }, 1864 1865 start_compute_column_spans() { console.time("compute_column_spans"); }, 1866 end_compute_column_spans() { console.timeEnd("compute_column_spans"); }, 1867 1868 start_generated_location_for() { console.time("generated_location_for"); }, 1869 end_generated_location_for() { console.timeEnd("generated_location_for"); }, 1870 1871 start_original_location_for() { console.time("original_location_for"); }, 1872 end_original_location_for() { console.timeEnd("original_location_for"); }, 1873 1874 start_parse_mappings() { console.time("parse_mappings"); }, 1875 end_parse_mappings() { console.timeEnd("parse_mappings"); }, 1876 1877 start_sort_by_generated_location() { console.time("sort_by_generated_location"); }, 1878 end_sort_by_generated_location() { console.timeEnd("sort_by_generated_location"); }, 1879 1880 start_sort_by_original_location() { console.time("sort_by_original_location"); }, 1881 end_sort_by_original_location() { console.timeEnd("sort_by_original_location"); }, 1882 } 1883 }); 1884 }).then(Wasm => { 1885 return { 1886 exports: Wasm.instance.exports, 1887 withMappingCallback: (mappingCallback, f) => { 1888 callbackStack.push(mappingCallback); 1889 try { 1890 f(); 1891 } finally { 1892 callbackStack.pop(); 1893 } 1894 } 1895 }; 1896 }).then(null, e => { 1897 cachedWasm = null; 1898 throw e; 1899 }); 1900 1901 return cachedWasm; 1902 }; 1903 return wasm; 1904 } 1905 1906 var hasRequiredSourceMapConsumer; 1907 1908 function requireSourceMapConsumer () { 1909 if (hasRequiredSourceMapConsumer) return sourceMapConsumer; 1910 hasRequiredSourceMapConsumer = 1; 1911 /* 1912 * Copyright 2011 Mozilla Foundation and contributors 1913 * Licensed under the New BSD license. See LICENSE or: 1914 * http://opensource.org/licenses/BSD-3-Clause 1915 */ 1916 1917 const util = requireUtil(); 1918 const binarySearch = requireBinarySearch(); 1919 const ArraySet = requireArraySet().ArraySet; 1920 requireBase64Vlq(); // eslint-disable-line no-unused-vars 1921 const readWasm = requireReadWasm(); 1922 const wasm = requireWasm(); 1923 1924 const INTERNAL = Symbol("smcInternal"); 1925 1926 class SourceMapConsumer { 1927 constructor(aSourceMap, aSourceMapURL) { 1928 // If the constructor was called by super(), just return Promise<this>. 1929 // Yes, this is a hack to retain the pre-existing API of the base-class 1930 // constructor also being an async factory function. 1931 if (aSourceMap == INTERNAL) { 1932 return Promise.resolve(this); 1933 } 1934 1935 return _factory(aSourceMap, aSourceMapURL); 1936 } 1937 1938 static initialize(opts) { 1939 readWasm.initialize(opts["lib/mappings.wasm"]); 1940 } 1941 1942 static fromSourceMap(aSourceMap, aSourceMapURL) { 1943 return _factoryBSM(aSourceMap, aSourceMapURL); 1944 } 1945 1946 /** 1947 * Construct a new `SourceMapConsumer` from `rawSourceMap` and `sourceMapUrl` 1948 * (see the `SourceMapConsumer` constructor for details. Then, invoke the `async 1949 * function f(SourceMapConsumer) -> T` with the newly constructed consumer, wait 1950 * for `f` to complete, call `destroy` on the consumer, and return `f`'s return 1951 * value. 1952 * 1953 * You must not use the consumer after `f` completes! 1954 * 1955 * By using `with`, you do not have to remember to manually call `destroy` on 1956 * the consumer, since it will be called automatically once `f` completes. 1957 * 1958 * ```js 1959 * const xSquared = await SourceMapConsumer.with( 1960 * myRawSourceMap, 1961 * null, 1962 * async function (consumer) { 1963 * // Use `consumer` inside here and don't worry about remembering 1964 * // to call `destroy`. 1965 * 1966 * const x = await whatever(consumer); 1967 * return x * x; 1968 * } 1969 * ); 1970 * 1971 * // You may not use that `consumer` anymore out here; it has 1972 * // been destroyed. But you can use `xSquared`. 1973 * console.log(xSquared); 1974 * ``` 1975 */ 1976 static async with(rawSourceMap, sourceMapUrl, f) { 1977 const consumer = await new SourceMapConsumer(rawSourceMap, sourceMapUrl); 1978 try { 1979 return await f(consumer); 1980 } finally { 1981 consumer.destroy(); 1982 } 1983 } 1984 1985 /** 1986 * Parse the mappings in a string in to a data structure which we can easily 1987 * query (the ordered arrays in the `this.__generatedMappings` and 1988 * `this.__originalMappings` properties). 1989 */ 1990 _parseMappings(aStr, aSourceRoot) { 1991 throw new Error("Subclasses must implement _parseMappings"); 1992 } 1993 1994 /** 1995 * Iterate over each mapping between an original source/line/column and a 1996 * generated line/column in this source map. 1997 * 1998 * @param Function aCallback 1999 * The function that is called with each mapping. 2000 * @param Object aContext 2001 * Optional. If specified, this object will be the value of `this` every 2002 * time that `aCallback` is called. 2003 * @param aOrder 2004 * Either `SourceMapConsumer.GENERATED_ORDER` or 2005 * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to 2006 * iterate over the mappings sorted by the generated file's line/column 2007 * order or the original's source/line/column order, respectively. Defaults to 2008 * `SourceMapConsumer.GENERATED_ORDER`. 2009 */ 2010 eachMapping(aCallback, aContext, aOrder) { 2011 throw new Error("Subclasses must implement eachMapping"); 2012 } 2013 2014 /** 2015 * Returns all generated line and column information for the original source, 2016 * line, and column provided. If no column is provided, returns all mappings 2017 * corresponding to a either the line we are searching for or the next 2018 * closest line that has any mappings. Otherwise, returns all mappings 2019 * corresponding to the given line and either the column we are searching for 2020 * or the next closest column that has any offsets. 2021 * 2022 * The only argument is an object with the following properties: 2023 * 2024 * - source: The filename of the original source. 2025 * - line: The line number in the original source. The line number is 1-based. 2026 * - column: Optional. the column number in the original source. 2027 * The column number is 0-based. 2028 * 2029 * and an array of objects is returned, each with the following properties: 2030 * 2031 * - line: The line number in the generated source, or null. The 2032 * line number is 1-based. 2033 * - column: The column number in the generated source, or null. 2034 * The column number is 0-based. 2035 */ 2036 allGeneratedPositionsFor(aArgs) { 2037 throw new Error("Subclasses must implement allGeneratedPositionsFor"); 2038 } 2039 2040 destroy() { 2041 throw new Error("Subclasses must implement destroy"); 2042 } 2043 } 2044 2045 /** 2046 * The version of the source mapping spec that we are consuming. 2047 */ 2048 SourceMapConsumer.prototype._version = 3; 2049 SourceMapConsumer.GENERATED_ORDER = 1; 2050 SourceMapConsumer.ORIGINAL_ORDER = 2; 2051 2052 SourceMapConsumer.GREATEST_LOWER_BOUND = 1; 2053 SourceMapConsumer.LEAST_UPPER_BOUND = 2; 2054 2055 sourceMapConsumer.SourceMapConsumer = SourceMapConsumer; 2056 2057 /** 2058 * A BasicSourceMapConsumer instance represents a parsed source map which we can 2059 * query for information about the original file positions by giving it a file 2060 * position in the generated source. 2061 * 2062 * The first parameter is the raw source map (either as a JSON string, or 2063 * already parsed to an object). According to the spec, source maps have the 2064 * following attributes: 2065 * 2066 * - version: Which version of the source map spec this map is following. 2067 * - sources: An array of URLs to the original source files. 2068 * - names: An array of identifiers which can be referenced by individual mappings. 2069 * - sourceRoot: Optional. The URL root from which all sources are relative. 2070 * - sourcesContent: Optional. An array of contents of the original source files. 2071 * - mappings: A string of base64 VLQs which contain the actual mappings. 2072 * - file: Optional. The generated file this source map is associated with. 2073 * 2074 * Here is an example source map, taken from the source map spec[0]: 2075 * 2076 * { 2077 * version : 3, 2078 * file: "out.js", 2079 * sourceRoot : "", 2080 * sources: ["foo.js", "bar.js"], 2081 * names: ["src", "maps", "are", "fun"], 2082 * mappings: "AA,AB;;ABCDE;" 2083 * } 2084 * 2085 * The second parameter, if given, is a string whose value is the URL 2086 * at which the source map was found. This URL is used to compute the 2087 * sources array. 2088 * 2089 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# 2090 */ 2091 class BasicSourceMapConsumer extends SourceMapConsumer { 2092 constructor(aSourceMap, aSourceMapURL) { 2093 return super(INTERNAL).then(that => { 2094 let sourceMap = aSourceMap; 2095 if (typeof aSourceMap === "string") { 2096 sourceMap = util.parseSourceMapInput(aSourceMap); 2097 } 2098 2099 const version = util.getArg(sourceMap, "version"); 2100 let sources = util.getArg(sourceMap, "sources"); 2101 // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which 2102 // requires the array) to play nice here. 2103 const names = util.getArg(sourceMap, "names", []); 2104 let sourceRoot = util.getArg(sourceMap, "sourceRoot", null); 2105 const sourcesContent = util.getArg(sourceMap, "sourcesContent", null); 2106 const mappings = util.getArg(sourceMap, "mappings"); 2107 const file = util.getArg(sourceMap, "file", null); 2108 2109 // Once again, Sass deviates from the spec and supplies the version as a 2110 // string rather than a number, so we use loose equality checking here. 2111 if (version != that._version) { 2112 throw new Error("Unsupported version: " + version); 2113 } 2114 2115 if (sourceRoot) { 2116 sourceRoot = util.normalize(sourceRoot); 2117 } 2118 2119 sources = sources 2120 .map(String) 2121 // Some source maps produce relative source paths like "./foo.js" instead of 2122 // "foo.js". Normalize these first so that future comparisons will succeed. 2123 // See bugzil.la/1090768. 2124 .map(util.normalize) 2125 // Always ensure that absolute sources are internally stored relative to 2126 // the source root, if the source root is absolute. Not doing this would 2127 // be particularly problematic when the source root is a prefix of the 2128 // source (valid, but why??). See github issue #199 and bugzil.la/1188982. 2129 .map(function(source) { 2130 return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) 2131 ? util.relative(sourceRoot, source) 2132 : source; 2133 }); 2134 2135 // Pass `true` below to allow duplicate names and sources. While source maps 2136 // are intended to be compressed and deduplicated, the TypeScript compiler 2137 // sometimes generates source maps with duplicates in them. See Github issue 2138 // #72 and bugzil.la/889492. 2139 that._names = ArraySet.fromArray(names.map(String), true); 2140 that._sources = ArraySet.fromArray(sources, true); 2141 2142 that._absoluteSources = that._sources.toArray().map(function(s) { 2143 return util.computeSourceURL(sourceRoot, s, aSourceMapURL); 2144 }); 2145 2146 that.sourceRoot = sourceRoot; 2147 that.sourcesContent = sourcesContent; 2148 that._mappings = mappings; 2149 that._sourceMapURL = aSourceMapURL; 2150 that.file = file; 2151 2152 that._computedColumnSpans = false; 2153 that._mappingsPtr = 0; 2154 that._wasm = null; 2155 2156 return wasm().then(w => { 2157 that._wasm = w; 2158 return that; 2159 }); 2160 }); 2161 } 2162 2163 /** 2164 * Utility function to find the index of a source. Returns -1 if not 2165 * found. 2166 */ 2167 _findSourceIndex(aSource) { 2168 let relativeSource = aSource; 2169 if (this.sourceRoot != null) { 2170 relativeSource = util.relative(this.sourceRoot, relativeSource); 2171 } 2172 2173 if (this._sources.has(relativeSource)) { 2174 return this._sources.indexOf(relativeSource); 2175 } 2176 2177 // Maybe aSource is an absolute URL as returned by |sources|. In 2178 // this case we can't simply undo the transform. 2179 for (let i = 0; i < this._absoluteSources.length; ++i) { 2180 if (this._absoluteSources[i] == aSource) { 2181 return i; 2182 } 2183 } 2184 2185 return -1; 2186 } 2187 2188 /** 2189 * Create a BasicSourceMapConsumer from a SourceMapGenerator. 2190 * 2191 * @param SourceMapGenerator aSourceMap 2192 * The source map that will be consumed. 2193 * @param String aSourceMapURL 2194 * The URL at which the source map can be found (optional) 2195 * @returns BasicSourceMapConsumer 2196 */ 2197 static fromSourceMap(aSourceMap, aSourceMapURL) { 2198 return new BasicSourceMapConsumer(aSourceMap.toString()); 2199 } 2200 2201 get sources() { 2202 return this._absoluteSources.slice(); 2203 } 2204 2205 _getMappingsPtr() { 2206 if (this._mappingsPtr === 0) { 2207 this._parseMappings(this._mappings, this.sourceRoot); 2208 } 2209 2210 return this._mappingsPtr; 2211 } 2212 2213 /** 2214 * Parse the mappings in a string in to a data structure which we can easily 2215 * query (the ordered arrays in the `this.__generatedMappings` and 2216 * `this.__originalMappings` properties). 2217 */ 2218 _parseMappings(aStr, aSourceRoot) { 2219 const size = aStr.length; 2220 2221 const mappingsBufPtr = this._wasm.exports.allocate_mappings(size); 2222 const mappingsBuf = new Uint8Array(this._wasm.exports.memory.buffer, mappingsBufPtr, size); 2223 for (let i = 0; i < size; i++) { 2224 mappingsBuf[i] = aStr.charCodeAt(i); 2225 } 2226 2227 const mappingsPtr = this._wasm.exports.parse_mappings(mappingsBufPtr); 2228 2229 if (!mappingsPtr) { 2230 const error = this._wasm.exports.get_last_error(); 2231 let msg = `Error parsing mappings (code ${error}): `; 2232 2233 // XXX: keep these error codes in sync with `fitzgen/source-map-mappings`. 2234 switch (error) { 2235 case 1: 2236 msg += "the mappings contained a negative line, column, source index, or name index"; 2237 break; 2238 case 2: 2239 msg += "the mappings contained a number larger than 2**32"; 2240 break; 2241 case 3: 2242 msg += "reached EOF while in the middle of parsing a VLQ"; 2243 break; 2244 case 4: 2245 msg += "invalid base 64 character while parsing a VLQ"; 2246 break; 2247 default: 2248 msg += "unknown error code"; 2249 break; 2250 } 2251 2252 throw new Error(msg); 2253 } 2254 2255 this._mappingsPtr = mappingsPtr; 2256 } 2257 2258 eachMapping(aCallback, aContext, aOrder) { 2259 const context = aContext || null; 2260 const order = aOrder || SourceMapConsumer.GENERATED_ORDER; 2261 const sourceRoot = this.sourceRoot; 2262 2263 this._wasm.withMappingCallback( 2264 mapping => { 2265 if (mapping.source !== null) { 2266 mapping.source = this._sources.at(mapping.source); 2267 mapping.source = util.computeSourceURL(sourceRoot, mapping.source, this._sourceMapURL); 2268 2269 if (mapping.name !== null) { 2270 mapping.name = this._names.at(mapping.name); 2271 } 2272 } 2273 2274 aCallback.call(context, mapping); 2275 }, 2276 () => { 2277 switch (order) { 2278 case SourceMapConsumer.GENERATED_ORDER: 2279 this._wasm.exports.by_generated_location(this._getMappingsPtr()); 2280 break; 2281 case SourceMapConsumer.ORIGINAL_ORDER: 2282 this._wasm.exports.by_original_location(this._getMappingsPtr()); 2283 break; 2284 default: 2285 throw new Error("Unknown order of iteration."); 2286 } 2287 } 2288 ); 2289 } 2290 2291 allGeneratedPositionsFor(aArgs) { 2292 let source = util.getArg(aArgs, "source"); 2293 const originalLine = util.getArg(aArgs, "line"); 2294 const originalColumn = aArgs.column || 0; 2295 2296 source = this._findSourceIndex(source); 2297 if (source < 0) { 2298 return []; 2299 } 2300 2301 if (originalLine < 1) { 2302 throw new Error("Line numbers must be >= 1"); 2303 } 2304 2305 if (originalColumn < 0) { 2306 throw new Error("Column numbers must be >= 0"); 2307 } 2308 2309 const mappings = []; 2310 2311 this._wasm.withMappingCallback( 2312 m => { 2313 let lastColumn = m.lastGeneratedColumn; 2314 if (this._computedColumnSpans && lastColumn === null) { 2315 lastColumn = Infinity; 2316 } 2317 mappings.push({ 2318 line: m.generatedLine, 2319 column: m.generatedColumn, 2320 lastColumn, 2321 }); 2322 }, () => { 2323 this._wasm.exports.all_generated_locations_for( 2324 this._getMappingsPtr(), 2325 source, 2326 originalLine - 1, 2327 "column" in aArgs, 2328 originalColumn 2329 ); 2330 } 2331 ); 2332 2333 return mappings; 2334 } 2335 2336 destroy() { 2337 if (this._mappingsPtr !== 0) { 2338 this._wasm.exports.free_mappings(this._mappingsPtr); 2339 this._mappingsPtr = 0; 2340 } 2341 } 2342 2343 /** 2344 * Compute the last column for each generated mapping. The last column is 2345 * inclusive. 2346 */ 2347 computeColumnSpans() { 2348 if (this._computedColumnSpans) { 2349 return; 2350 } 2351 2352 this._wasm.exports.compute_column_spans(this._getMappingsPtr()); 2353 this._computedColumnSpans = true; 2354 } 2355 2356 /** 2357 * Returns the original source, line, and column information for the generated 2358 * source's line and column positions provided. The only argument is an object 2359 * with the following properties: 2360 * 2361 * - line: The line number in the generated source. The line number 2362 * is 1-based. 2363 * - column: The column number in the generated source. The column 2364 * number is 0-based. 2365 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or 2366 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the 2367 * closest element that is smaller than or greater than the one we are 2368 * searching for, respectively, if the exact element cannot be found. 2369 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. 2370 * 2371 * and an object is returned with the following properties: 2372 * 2373 * - source: The original source file, or null. 2374 * - line: The line number in the original source, or null. The 2375 * line number is 1-based. 2376 * - column: The column number in the original source, or null. The 2377 * column number is 0-based. 2378 * - name: The original identifier, or null. 2379 */ 2380 originalPositionFor(aArgs) { 2381 const needle = { 2382 generatedLine: util.getArg(aArgs, "line"), 2383 generatedColumn: util.getArg(aArgs, "column") 2384 }; 2385 2386 if (needle.generatedLine < 1) { 2387 throw new Error("Line numbers must be >= 1"); 2388 } 2389 2390 if (needle.generatedColumn < 0) { 2391 throw new Error("Column numbers must be >= 0"); 2392 } 2393 2394 let bias = util.getArg(aArgs, "bias", SourceMapConsumer.GREATEST_LOWER_BOUND); 2395 if (bias == null) { 2396 bias = SourceMapConsumer.GREATEST_LOWER_BOUND; 2397 } 2398 2399 let mapping; 2400 this._wasm.withMappingCallback(m => mapping = m, () => { 2401 this._wasm.exports.original_location_for( 2402 this._getMappingsPtr(), 2403 needle.generatedLine - 1, 2404 needle.generatedColumn, 2405 bias 2406 ); 2407 }); 2408 2409 if (mapping) { 2410 if (mapping.generatedLine === needle.generatedLine) { 2411 let source = util.getArg(mapping, "source", null); 2412 if (source !== null) { 2413 source = this._sources.at(source); 2414 source = util.computeSourceURL(this.sourceRoot, source, this._sourceMapURL); 2415 } 2416 2417 let name = util.getArg(mapping, "name", null); 2418 if (name !== null) { 2419 name = this._names.at(name); 2420 } 2421 2422 return { 2423 source, 2424 line: util.getArg(mapping, "originalLine", null), 2425 column: util.getArg(mapping, "originalColumn", null), 2426 name 2427 }; 2428 } 2429 } 2430 2431 return { 2432 source: null, 2433 line: null, 2434 column: null, 2435 name: null 2436 }; 2437 } 2438 2439 /** 2440 * Return true if we have the source content for every source in the source 2441 * map, false otherwise. 2442 */ 2443 hasContentsOfAllSources() { 2444 if (!this.sourcesContent) { 2445 return false; 2446 } 2447 return this.sourcesContent.length >= this._sources.size() && 2448 !this.sourcesContent.some(function(sc) { return sc == null; }); 2449 } 2450 2451 /** 2452 * Returns the original source content. The only argument is the url of the 2453 * original source file. Returns null if no original source content is 2454 * available. 2455 */ 2456 sourceContentFor(aSource, nullOnMissing) { 2457 if (!this.sourcesContent) { 2458 return null; 2459 } 2460 2461 const index = this._findSourceIndex(aSource); 2462 if (index >= 0) { 2463 return this.sourcesContent[index]; 2464 } 2465 2466 let relativeSource = aSource; 2467 if (this.sourceRoot != null) { 2468 relativeSource = util.relative(this.sourceRoot, relativeSource); 2469 } 2470 2471 let url; 2472 if (this.sourceRoot != null 2473 && (url = util.urlParse(this.sourceRoot))) { 2474 // XXX: file:// URIs and absolute paths lead to unexpected behavior for 2475 // many users. We can help them out when they expect file:// URIs to 2476 // behave like it would if they were running a local HTTP server. See 2477 // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. 2478 const fileUriAbsPath = relativeSource.replace(/^file:\/\//, ""); 2479 if (url.scheme == "file" 2480 && this._sources.has(fileUriAbsPath)) { 2481 return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]; 2482 } 2483 2484 if ((!url.path || url.path == "/") 2485 && this._sources.has("/" + relativeSource)) { 2486 return this.sourcesContent[this._sources.indexOf("/" + relativeSource)]; 2487 } 2488 } 2489 2490 // This function is used recursively from 2491 // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we 2492 // don't want to throw if we can't find the source - we just want to 2493 // return null, so we provide a flag to exit gracefully. 2494 if (nullOnMissing) { 2495 return null; 2496 } 2497 2498 throw new Error('"' + relativeSource + '" is not in the SourceMap.'); 2499 } 2500 2501 /** 2502 * Returns the generated line and column information for the original source, 2503 * line, and column positions provided. The only argument is an object with 2504 * the following properties: 2505 * 2506 * - source: The filename of the original source. 2507 * - line: The line number in the original source. The line number 2508 * is 1-based. 2509 * - column: The column number in the original source. The column 2510 * number is 0-based. 2511 * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or 2512 * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the 2513 * closest element that is smaller than or greater than the one we are 2514 * searching for, respectively, if the exact element cannot be found. 2515 * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. 2516 * 2517 * and an object is returned with the following properties: 2518 * 2519 * - line: The line number in the generated source, or null. The 2520 * line number is 1-based. 2521 * - column: The column number in the generated source, or null. 2522 * The column number is 0-based. 2523 */ 2524 generatedPositionFor(aArgs) { 2525 let source = util.getArg(aArgs, "source"); 2526 source = this._findSourceIndex(source); 2527 if (source < 0) { 2528 return { 2529 line: null, 2530 column: null, 2531 lastColumn: null 2532 }; 2533 } 2534 2535 const needle = { 2536 source, 2537 originalLine: util.getArg(aArgs, "line"), 2538 originalColumn: util.getArg(aArgs, "column") 2539 }; 2540 2541 if (needle.originalLine < 1) { 2542 throw new Error("Line numbers must be >= 1"); 2543 } 2544 2545 if (needle.originalColumn < 0) { 2546 throw new Error("Column numbers must be >= 0"); 2547 } 2548 2549 let bias = util.getArg(aArgs, "bias", SourceMapConsumer.GREATEST_LOWER_BOUND); 2550 if (bias == null) { 2551 bias = SourceMapConsumer.GREATEST_LOWER_BOUND; 2552 } 2553 2554 let mapping; 2555 this._wasm.withMappingCallback(m => mapping = m, () => { 2556 this._wasm.exports.generated_location_for( 2557 this._getMappingsPtr(), 2558 needle.source, 2559 needle.originalLine - 1, 2560 needle.originalColumn, 2561 bias 2562 ); 2563 }); 2564 2565 if (mapping) { 2566 if (mapping.source === needle.source) { 2567 let lastColumn = mapping.lastGeneratedColumn; 2568 if (this._computedColumnSpans && lastColumn === null) { 2569 lastColumn = Infinity; 2570 } 2571 return { 2572 line: util.getArg(mapping, "generatedLine", null), 2573 column: util.getArg(mapping, "generatedColumn", null), 2574 lastColumn, 2575 }; 2576 } 2577 } 2578 2579 return { 2580 line: null, 2581 column: null, 2582 lastColumn: null 2583 }; 2584 } 2585 } 2586 2587 BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; 2588 sourceMapConsumer.BasicSourceMapConsumer = BasicSourceMapConsumer; 2589 2590 /** 2591 * An IndexedSourceMapConsumer instance represents a parsed source map which 2592 * we can query for information. It differs from BasicSourceMapConsumer in 2593 * that it takes "indexed" source maps (i.e. ones with a "sections" field) as 2594 * input. 2595 * 2596 * The first parameter is a raw source map (either as a JSON string, or already 2597 * parsed to an object). According to the spec for indexed source maps, they 2598 * have the following attributes: 2599 * 2600 * - version: Which version of the source map spec this map is following. 2601 * - file: Optional. The generated file this source map is associated with. 2602 * - sections: A list of section definitions. 2603 * 2604 * Each value under the "sections" field has two fields: 2605 * - offset: The offset into the original specified at which this section 2606 * begins to apply, defined as an object with a "line" and "column" 2607 * field. 2608 * - map: A source map definition. This source map could also be indexed, 2609 * but doesn't have to be. 2610 * 2611 * Instead of the "map" field, it's also possible to have a "url" field 2612 * specifying a URL to retrieve a source map from, but that's currently 2613 * unsupported. 2614 * 2615 * Here's an example source map, taken from the source map spec[0], but 2616 * modified to omit a section which uses the "url" field. 2617 * 2618 * { 2619 * version : 3, 2620 * file: "app.js", 2621 * sections: [{ 2622 * offset: {line:100, column:10}, 2623 * map: { 2624 * version : 3, 2625 * file: "section.js", 2626 * sources: ["foo.js", "bar.js"], 2627 * names: ["src", "maps", "are", "fun"], 2628 * mappings: "AAAA,E;;ABCDE;" 2629 * } 2630 * }], 2631 * } 2632 * 2633 * The second parameter, if given, is a string whose value is the URL 2634 * at which the source map was found. This URL is used to compute the 2635 * sources array. 2636 * 2637 * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt 2638 */ 2639 class IndexedSourceMapConsumer extends SourceMapConsumer { 2640 constructor(aSourceMap, aSourceMapURL) { 2641 return super(INTERNAL).then(that => { 2642 let sourceMap = aSourceMap; 2643 if (typeof aSourceMap === "string") { 2644 sourceMap = util.parseSourceMapInput(aSourceMap); 2645 } 2646 2647 const version = util.getArg(sourceMap, "version"); 2648 const sections = util.getArg(sourceMap, "sections"); 2649 2650 if (version != that._version) { 2651 throw new Error("Unsupported version: " + version); 2652 } 2653 2654 that._sources = new ArraySet(); 2655 that._names = new ArraySet(); 2656 that.__generatedMappings = null; 2657 that.__originalMappings = null; 2658 that.__generatedMappingsUnsorted = null; 2659 that.__originalMappingsUnsorted = null; 2660 2661 let lastOffset = { 2662 line: -1, 2663 column: 0 2664 }; 2665 return Promise.all(sections.map(s => { 2666 if (s.url) { 2667 // The url field will require support for asynchronicity. 2668 // See https://github.com/mozilla/source-map/issues/16 2669 throw new Error("Support for url field in sections not implemented."); 2670 } 2671 const offset = util.getArg(s, "offset"); 2672 const offsetLine = util.getArg(offset, "line"); 2673 const offsetColumn = util.getArg(offset, "column"); 2674 2675 if (offsetLine < lastOffset.line || 2676 (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { 2677 throw new Error("Section offsets must be ordered and non-overlapping."); 2678 } 2679 lastOffset = offset; 2680 2681 const cons = new SourceMapConsumer(util.getArg(s, "map"), aSourceMapURL); 2682 return cons.then(consumer => { 2683 return { 2684 generatedOffset: { 2685 // The offset fields are 0-based, but we use 1-based indices when 2686 // encoding/decoding from VLQ. 2687 generatedLine: offsetLine + 1, 2688 generatedColumn: offsetColumn + 1 2689 }, 2690 consumer 2691 }; 2692 }); 2693 })).then(s => { 2694 that._sections = s; 2695 return that; 2696 }); 2697 }); 2698 } 2699 2700 // `__generatedMappings` and `__originalMappings` are arrays that hold the 2701 // parsed mapping coordinates from the source map's "mappings" attribute. They 2702 // are lazily instantiated, accessed via the `_generatedMappings` and 2703 // `_originalMappings` getters respectively, and we only parse the mappings 2704 // and create these arrays once queried for a source location. We jump through 2705 // these hoops because there can be many thousands of mappings, and parsing 2706 // them is expensive, so we only want to do it if we must. 2707 // 2708 // Each object in the arrays is of the form: 2709 // 2710 // { 2711 // generatedLine: The line number in the generated code, 2712 // generatedColumn: The column number in the generated code, 2713 // source: The path to the original source file that generated this 2714 // chunk of code, 2715 // originalLine: The line number in the original source that 2716 // corresponds to this chunk of generated code, 2717 // originalColumn: The column number in the original source that 2718 // corresponds to this chunk of generated code, 2719 // name: The name of the original symbol which generated this chunk of 2720 // code. 2721 // } 2722 // 2723 // All properties except for `generatedLine` and `generatedColumn` can be 2724 // `null`. 2725 // 2726 // `_generatedMappings` is ordered by the generated positions. 2727 // 2728 // `_originalMappings` is ordered by the original positions. 2729 get _generatedMappings() { 2730 if (!this.__generatedMappings) { 2731 this._sortGeneratedMappings(); 2732 } 2733 2734 return this.__generatedMappings; 2735 } 2736 2737 get _originalMappings() { 2738 if (!this.__originalMappings) { 2739 this._sortOriginalMappings(); 2740 } 2741 2742 return this.__originalMappings; 2743 } 2744 2745 get _generatedMappingsUnsorted() { 2746 if (!this.__generatedMappingsUnsorted) { 2747 this._parseMappings(this._mappings, this.sourceRoot); 2748 } 2749 2750 return this.__generatedMappingsUnsorted; 2751 } 2752 2753 get _originalMappingsUnsorted() { 2754 if (!this.__originalMappingsUnsorted) { 2755 this._parseMappings(this._mappings, this.sourceRoot); 2756 } 2757 2758 return this.__originalMappingsUnsorted; 2759 } 2760 2761 _sortGeneratedMappings() { 2762 const mappings = this._generatedMappingsUnsorted; 2763 mappings.sort(util.compareByGeneratedPositionsDeflated); 2764 this.__generatedMappings = mappings; 2765 } 2766 2767 _sortOriginalMappings() { 2768 const mappings = this._originalMappingsUnsorted; 2769 mappings.sort(util.compareByOriginalPositions); 2770 this.__originalMappings = mappings; 2771 } 2772 2773 /** 2774 * The list of original sources. 2775 */ 2776 get sources() { 2777 const sources = []; 2778 for (let i = 0; i < this._sections.length; i++) { 2779 for (let j = 0; j < this._sections[i].consumer.sources.length; j++) { 2780 sources.push(this._sections[i].consumer.sources[j]); 2781 } 2782 } 2783 return sources; 2784 } 2785 2786 /** 2787 * Returns the original source, line, and column information for the generated 2788 * source's line and column positions provided. The only argument is an object 2789 * with the following properties: 2790 * 2791 * - line: The line number in the generated source. The line number 2792 * is 1-based. 2793 * - column: The column number in the generated source. The column 2794 * number is 0-based. 2795 * 2796 * and an object is returned with the following properties: 2797 * 2798 * - source: The original source file, or null. 2799 * - line: The line number in the original source, or null. The 2800 * line number is 1-based. 2801 * - column: The column number in the original source, or null. The 2802 * column number is 0-based. 2803 * - name: The original identifier, or null. 2804 */ 2805 originalPositionFor(aArgs) { 2806 const needle = { 2807 generatedLine: util.getArg(aArgs, "line"), 2808 generatedColumn: util.getArg(aArgs, "column") 2809 }; 2810 2811 // Find the section containing the generated position we're trying to map 2812 // to an original position. 2813 const sectionIndex = binarySearch.search(needle, this._sections, 2814 function(aNeedle, section) { 2815 const cmp = aNeedle.generatedLine - section.generatedOffset.generatedLine; 2816 if (cmp) { 2817 return cmp; 2818 } 2819 2820 return (aNeedle.generatedColumn - 2821 section.generatedOffset.generatedColumn); 2822 }); 2823 const section = this._sections[sectionIndex]; 2824 2825 if (!section) { 2826 return { 2827 source: null, 2828 line: null, 2829 column: null, 2830 name: null 2831 }; 2832 } 2833 2834 return section.consumer.originalPositionFor({ 2835 line: needle.generatedLine - 2836 (section.generatedOffset.generatedLine - 1), 2837 column: needle.generatedColumn - 2838 (section.generatedOffset.generatedLine === needle.generatedLine 2839 ? section.generatedOffset.generatedColumn - 1 2840 : 0), 2841 bias: aArgs.bias 2842 }); 2843 } 2844 2845 /** 2846 * Return true if we have the source content for every source in the source 2847 * map, false otherwise. 2848 */ 2849 hasContentsOfAllSources() { 2850 return this._sections.every(function(s) { 2851 return s.consumer.hasContentsOfAllSources(); 2852 }); 2853 } 2854 2855 /** 2856 * Returns the original source content. The only argument is the url of the 2857 * original source file. Returns null if no original source content is 2858 * available. 2859 */ 2860 sourceContentFor(aSource, nullOnMissing) { 2861 for (let i = 0; i < this._sections.length; i++) { 2862 const section = this._sections[i]; 2863 2864 const content = section.consumer.sourceContentFor(aSource, true); 2865 if (content) { 2866 return content; 2867 } 2868 } 2869 if (nullOnMissing) { 2870 return null; 2871 } 2872 throw new Error('"' + aSource + '" is not in the SourceMap.'); 2873 } 2874 2875 /** 2876 * Returns the generated line and column information for the original source, 2877 * line, and column positions provided. The only argument is an object with 2878 * the following properties: 2879 * 2880 * - source: The filename of the original source. 2881 * - line: The line number in the original source. The line number 2882 * is 1-based. 2883 * - column: The column number in the original source. The column 2884 * number is 0-based. 2885 * 2886 * and an object is returned with the following properties: 2887 * 2888 * - line: The line number in the generated source, or null. The 2889 * line number is 1-based. 2890 * - column: The column number in the generated source, or null. 2891 * The column number is 0-based. 2892 */ 2893 generatedPositionFor(aArgs) { 2894 for (let i = 0; i < this._sections.length; i++) { 2895 const section = this._sections[i]; 2896 2897 // Only consider this section if the requested source is in the list of 2898 // sources of the consumer. 2899 if (section.consumer._findSourceIndex(util.getArg(aArgs, "source")) === -1) { 2900 continue; 2901 } 2902 const generatedPosition = section.consumer.generatedPositionFor(aArgs); 2903 if (generatedPosition) { 2904 const ret = { 2905 line: generatedPosition.line + 2906 (section.generatedOffset.generatedLine - 1), 2907 column: generatedPosition.column + 2908 (section.generatedOffset.generatedLine === generatedPosition.line 2909 ? section.generatedOffset.generatedColumn - 1 2910 : 0) 2911 }; 2912 return ret; 2913 } 2914 } 2915 2916 return { 2917 line: null, 2918 column: null 2919 }; 2920 } 2921 2922 /** 2923 * Parse the mappings in a string in to a data structure which we can easily 2924 * query (the ordered arrays in the `this.__generatedMappings` and 2925 * `this.__originalMappings` properties). 2926 */ 2927 _parseMappings(aStr, aSourceRoot) { 2928 const generatedMappings = this.__generatedMappingsUnsorted = []; 2929 const originalMappings = this.__originalMappingsUnsorted = []; 2930 for (let i = 0; i < this._sections.length; i++) { 2931 const section = this._sections[i]; 2932 2933 const sectionMappings = []; 2934 section.consumer.eachMapping(m => sectionMappings.push(m)); 2935 2936 for (let j = 0; j < sectionMappings.length; j++) { 2937 const mapping = sectionMappings[j]; 2938 2939 // TODO: test if null is correct here. The original code used 2940 // `source`, which would actually have gotten used as null because 2941 // var's get hoisted. 2942 // See: https://github.com/mozilla/source-map/issues/333 2943 let source = util.computeSourceURL(section.consumer.sourceRoot, null, this._sourceMapURL); 2944 this._sources.add(source); 2945 source = this._sources.indexOf(source); 2946 2947 let name = null; 2948 if (mapping.name) { 2949 this._names.add(mapping.name); 2950 name = this._names.indexOf(mapping.name); 2951 } 2952 2953 // The mappings coming from the consumer for the section have 2954 // generated positions relative to the start of the section, so we 2955 // need to offset them to be relative to the start of the concatenated 2956 // generated file. 2957 const adjustedMapping = { 2958 source, 2959 generatedLine: mapping.generatedLine + 2960 (section.generatedOffset.generatedLine - 1), 2961 generatedColumn: mapping.generatedColumn + 2962 (section.generatedOffset.generatedLine === mapping.generatedLine 2963 ? section.generatedOffset.generatedColumn - 1 2964 : 0), 2965 originalLine: mapping.originalLine, 2966 originalColumn: mapping.originalColumn, 2967 name 2968 }; 2969 2970 generatedMappings.push(adjustedMapping); 2971 if (typeof adjustedMapping.originalLine === "number") { 2972 originalMappings.push(adjustedMapping); 2973 } 2974 } 2975 } 2976 } 2977 2978 eachMapping(aCallback, aContext, aOrder) { 2979 const context = aContext || null; 2980 const order = aOrder || SourceMapConsumer.GENERATED_ORDER; 2981 2982 let mappings; 2983 switch (order) { 2984 case SourceMapConsumer.GENERATED_ORDER: 2985 mappings = this._generatedMappings; 2986 break; 2987 case SourceMapConsumer.ORIGINAL_ORDER: 2988 mappings = this._originalMappings; 2989 break; 2990 default: 2991 throw new Error("Unknown order of iteration."); 2992 } 2993 2994 const sourceRoot = this.sourceRoot; 2995 mappings.map(function(mapping) { 2996 let source = null; 2997 if (mapping.source !== null) { 2998 source = this._sources.at(mapping.source); 2999 source = util.computeSourceURL(sourceRoot, source, this._sourceMapURL); 3000 } 3001 return { 3002 source, 3003 generatedLine: mapping.generatedLine, 3004 generatedColumn: mapping.generatedColumn, 3005 originalLine: mapping.originalLine, 3006 originalColumn: mapping.originalColumn, 3007 name: mapping.name === null ? null : this._names.at(mapping.name) 3008 }; 3009 }, this).forEach(aCallback, context); 3010 } 3011 3012 /** 3013 * Find the mapping that best matches the hypothetical "needle" mapping that 3014 * we are searching for in the given "haystack" of mappings. 3015 */ 3016 _findMapping(aNeedle, aMappings, aLineName, 3017 aColumnName, aComparator, aBias) { 3018 // To return the position we are searching for, we must first find the 3019 // mapping for the given position and then return the opposite position it 3020 // points to. Because the mappings are sorted, we can use binary search to 3021 // find the best mapping. 3022 3023 if (aNeedle[aLineName] <= 0) { 3024 throw new TypeError("Line must be greater than or equal to 1, got " 3025 + aNeedle[aLineName]); 3026 } 3027 if (aNeedle[aColumnName] < 0) { 3028 throw new TypeError("Column must be greater than or equal to 0, got " 3029 + aNeedle[aColumnName]); 3030 } 3031 3032 return binarySearch.search(aNeedle, aMappings, aComparator, aBias); 3033 } 3034 3035 allGeneratedPositionsFor(aArgs) { 3036 const line = util.getArg(aArgs, "line"); 3037 3038 // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping 3039 // returns the index of the closest mapping less than the needle. By 3040 // setting needle.originalColumn to 0, we thus find the last mapping for 3041 // the given line, provided such a mapping exists. 3042 const needle = { 3043 source: util.getArg(aArgs, "source"), 3044 originalLine: line, 3045 originalColumn: util.getArg(aArgs, "column", 0) 3046 }; 3047 3048 needle.source = this._findSourceIndex(needle.source); 3049 if (needle.source < 0) { 3050 return []; 3051 } 3052 3053 if (needle.originalLine < 1) { 3054 throw new Error("Line numbers must be >= 1"); 3055 } 3056 3057 if (needle.originalColumn < 0) { 3058 throw new Error("Column numbers must be >= 0"); 3059 } 3060 3061 const mappings = []; 3062 3063 let index = this._findMapping(needle, 3064 this._originalMappings, 3065 "originalLine", 3066 "originalColumn", 3067 util.compareByOriginalPositions, 3068 binarySearch.LEAST_UPPER_BOUND); 3069 if (index >= 0) { 3070 let mapping = this._originalMappings[index]; 3071 3072 if (aArgs.column === undefined) { 3073 const originalLine = mapping.originalLine; 3074 3075 // Iterate until either we run out of mappings, or we run into 3076 // a mapping for a different line than the one we found. Since 3077 // mappings are sorted, this is guaranteed to find all mappings for 3078 // the line we found. 3079 while (mapping && mapping.originalLine === originalLine) { 3080 let lastColumn = mapping.lastGeneratedColumn; 3081 if (this._computedColumnSpans && lastColumn === null) { 3082 lastColumn = Infinity; 3083 } 3084 mappings.push({ 3085 line: util.getArg(mapping, "generatedLine", null), 3086 column: util.getArg(mapping, "generatedColumn", null), 3087 lastColumn, 3088 }); 3089 3090 mapping = this._originalMappings[++index]; 3091 } 3092 } else { 3093 const originalColumn = mapping.originalColumn; 3094 3095 // Iterate until either we run out of mappings, or we run into 3096 // a mapping for a different line than the one we were searching for. 3097 // Since mappings are sorted, this is guaranteed to find all mappings for 3098 // the line we are searching for. 3099 while (mapping && 3100 mapping.originalLine === line && 3101 mapping.originalColumn == originalColumn) { 3102 let lastColumn = mapping.lastGeneratedColumn; 3103 if (this._computedColumnSpans && lastColumn === null) { 3104 lastColumn = Infinity; 3105 } 3106 mappings.push({ 3107 line: util.getArg(mapping, "generatedLine", null), 3108 column: util.getArg(mapping, "generatedColumn", null), 3109 lastColumn, 3110 }); 3111 3112 mapping = this._originalMappings[++index]; 3113 } 3114 } 3115 } 3116 3117 return mappings; 3118 } 3119 3120 destroy() { 3121 for (let i = 0; i < this._sections.length; i++) { 3122 this._sections[i].consumer.destroy(); 3123 } 3124 } 3125 } 3126 sourceMapConsumer.IndexedSourceMapConsumer = IndexedSourceMapConsumer; 3127 3128 /* 3129 * Cheat to get around inter-twingled classes. `factory()` can be at the end 3130 * where it has access to non-hoisted classes, but it gets hoisted itself. 3131 */ 3132 function _factory(aSourceMap, aSourceMapURL) { 3133 let sourceMap = aSourceMap; 3134 if (typeof aSourceMap === "string") { 3135 sourceMap = util.parseSourceMapInput(aSourceMap); 3136 } 3137 3138 const consumer = sourceMap.sections != null 3139 ? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL) 3140 : new BasicSourceMapConsumer(sourceMap, aSourceMapURL); 3141 return Promise.resolve(consumer); 3142 } 3143 3144 function _factoryBSM(aSourceMap, aSourceMapURL) { 3145 return BasicSourceMapConsumer.fromSourceMap(aSourceMap, aSourceMapURL); 3146 } 3147 return sourceMapConsumer; 3148 } 3149 3150 var sourceNode = {}; 3151 3152 var hasRequiredSourceNode; 3153 3154 function requireSourceNode () { 3155 if (hasRequiredSourceNode) return sourceNode; 3156 hasRequiredSourceNode = 1; 3157 /* 3158 * Copyright 2011 Mozilla Foundation and contributors 3159 * Licensed under the New BSD license. See LICENSE or: 3160 * http://opensource.org/licenses/BSD-3-Clause 3161 */ 3162 3163 const SourceMapGenerator = requireSourceMapGenerator().SourceMapGenerator; 3164 const util = requireUtil(); 3165 3166 // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other 3167 // operating systems these days (capturing the result). 3168 const REGEX_NEWLINE = /(\r?\n)/; 3169 3170 // Newline character code for charCodeAt() comparisons 3171 const NEWLINE_CODE = 10; 3172 3173 // Private symbol for identifying `SourceNode`s when multiple versions of 3174 // the source-map library are loaded. This MUST NOT CHANGE across 3175 // versions! 3176 const isSourceNode = "$$$isSourceNode$$$"; 3177 3178 /** 3179 * SourceNodes provide a way to abstract over interpolating/concatenating 3180 * snippets of generated JavaScript source code while maintaining the line and 3181 * column information associated with the original source code. 3182 * 3183 * @param aLine The original line number. 3184 * @param aColumn The original column number. 3185 * @param aSource The original source's filename. 3186 * @param aChunks Optional. An array of strings which are snippets of 3187 * generated JS, or other SourceNodes. 3188 * @param aName The original identifier. 3189 */ 3190 class SourceNode { 3191 constructor(aLine, aColumn, aSource, aChunks, aName) { 3192 this.children = []; 3193 this.sourceContents = {}; 3194 this.line = aLine == null ? null : aLine; 3195 this.column = aColumn == null ? null : aColumn; 3196 this.source = aSource == null ? null : aSource; 3197 this.name = aName == null ? null : aName; 3198 this[isSourceNode] = true; 3199 if (aChunks != null) this.add(aChunks); 3200 } 3201 3202 /** 3203 * Creates a SourceNode from generated code and a SourceMapConsumer. 3204 * 3205 * @param aGeneratedCode The generated code 3206 * @param aSourceMapConsumer The SourceMap for the generated code 3207 * @param aRelativePath Optional. The path that relative sources in the 3208 * SourceMapConsumer should be relative to. 3209 */ 3210 static fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { 3211 // The SourceNode we want to fill with the generated code 3212 // and the SourceMap 3213 const node = new SourceNode(); 3214 3215 // All even indices of this array are one line of the generated code, 3216 // while all odd indices are the newlines between two adjacent lines 3217 // (since `REGEX_NEWLINE` captures its match). 3218 // Processed fragments are accessed by calling `shiftNextLine`. 3219 const remainingLines = aGeneratedCode.split(REGEX_NEWLINE); 3220 let remainingLinesIndex = 0; 3221 const shiftNextLine = function() { 3222 const lineContents = getNextLine(); 3223 // The last line of a file might not have a newline. 3224 const newLine = getNextLine() || ""; 3225 return lineContents + newLine; 3226 3227 function getNextLine() { 3228 return remainingLinesIndex < remainingLines.length ? 3229 remainingLines[remainingLinesIndex++] : undefined; 3230 } 3231 }; 3232 3233 // We need to remember the position of "remainingLines" 3234 let lastGeneratedLine = 1, lastGeneratedColumn = 0; 3235 3236 // The generate SourceNodes we need a code range. 3237 // To extract it current and last mapping is used. 3238 // Here we store the last mapping. 3239 let lastMapping = null; 3240 let nextLine; 3241 3242 aSourceMapConsumer.eachMapping(function(mapping) { 3243 if (lastMapping !== null) { 3244 // We add the code from "lastMapping" to "mapping": 3245 // First check if there is a new line in between. 3246 if (lastGeneratedLine < mapping.generatedLine) { 3247 // Associate first line with "lastMapping" 3248 addMappingWithCode(lastMapping, shiftNextLine()); 3249 lastGeneratedLine++; 3250 lastGeneratedColumn = 0; 3251 // The remaining code is added without mapping 3252 } else { 3253 // There is no new line in between. 3254 // Associate the code between "lastGeneratedColumn" and 3255 // "mapping.generatedColumn" with "lastMapping" 3256 nextLine = remainingLines[remainingLinesIndex] || ""; 3257 const code = nextLine.substr(0, mapping.generatedColumn - 3258 lastGeneratedColumn); 3259 remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - 3260 lastGeneratedColumn); 3261 lastGeneratedColumn = mapping.generatedColumn; 3262 addMappingWithCode(lastMapping, code); 3263 // No more remaining code, continue 3264 lastMapping = mapping; 3265 return; 3266 } 3267 } 3268 // We add the generated code until the first mapping 3269 // to the SourceNode without any mapping. 3270 // Each line is added as separate string. 3271 while (lastGeneratedLine < mapping.generatedLine) { 3272 node.add(shiftNextLine()); 3273 lastGeneratedLine++; 3274 } 3275 if (lastGeneratedColumn < mapping.generatedColumn) { 3276 nextLine = remainingLines[remainingLinesIndex] || ""; 3277 node.add(nextLine.substr(0, mapping.generatedColumn)); 3278 remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); 3279 lastGeneratedColumn = mapping.generatedColumn; 3280 } 3281 lastMapping = mapping; 3282 }, this); 3283 // We have processed all mappings. 3284 if (remainingLinesIndex < remainingLines.length) { 3285 if (lastMapping) { 3286 // Associate the remaining code in the current line with "lastMapping" 3287 addMappingWithCode(lastMapping, shiftNextLine()); 3288 } 3289 // and add the remaining lines without any mapping 3290 node.add(remainingLines.splice(remainingLinesIndex).join("")); 3291 } 3292 3293 // Copy sourcesContent into SourceNode 3294 aSourceMapConsumer.sources.forEach(function(sourceFile) { 3295 const content = aSourceMapConsumer.sourceContentFor(sourceFile); 3296 if (content != null) { 3297 if (aRelativePath != null) { 3298 sourceFile = util.join(aRelativePath, sourceFile); 3299 } 3300 node.setSourceContent(sourceFile, content); 3301 } 3302 }); 3303 3304 return node; 3305 3306 function addMappingWithCode(mapping, code) { 3307 if (mapping === null || mapping.source === undefined) { 3308 node.add(code); 3309 } else { 3310 const source = aRelativePath 3311 ? util.join(aRelativePath, mapping.source) 3312 : mapping.source; 3313 node.add(new SourceNode(mapping.originalLine, 3314 mapping.originalColumn, 3315 source, 3316 code, 3317 mapping.name)); 3318 } 3319 } 3320 } 3321 3322 /** 3323 * Add a chunk of generated JS to this source node. 3324 * 3325 * @param aChunk A string snippet of generated JS code, another instance of 3326 * SourceNode, or an array where each member is one of those things. 3327 */ 3328 add(aChunk) { 3329 if (Array.isArray(aChunk)) { 3330 aChunk.forEach(function(chunk) { 3331 this.add(chunk); 3332 }, this); 3333 } else if (aChunk[isSourceNode] || typeof aChunk === "string") { 3334 if (aChunk) { 3335 this.children.push(aChunk); 3336 } 3337 } else { 3338 throw new TypeError( 3339 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 3340 ); 3341 } 3342 return this; 3343 } 3344 3345 /** 3346 * Add a chunk of generated JS to the beginning of this source node. 3347 * 3348 * @param aChunk A string snippet of generated JS code, another instance of 3349 * SourceNode, or an array where each member is one of those things. 3350 */ 3351 prepend(aChunk) { 3352 if (Array.isArray(aChunk)) { 3353 for (let i = aChunk.length - 1; i >= 0; i--) { 3354 this.prepend(aChunk[i]); 3355 } 3356 } else if (aChunk[isSourceNode] || typeof aChunk === "string") { 3357 this.children.unshift(aChunk); 3358 } else { 3359 throw new TypeError( 3360 "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk 3361 ); 3362 } 3363 return this; 3364 } 3365 3366 /** 3367 * Walk over the tree of JS snippets in this node and its children. The 3368 * walking function is called once for each snippet of JS and is passed that 3369 * snippet and the its original associated source's line/column location. 3370 * 3371 * @param aFn The traversal function. 3372 */ 3373 walk(aFn) { 3374 let chunk; 3375 for (let i = 0, len = this.children.length; i < len; i++) { 3376 chunk = this.children[i]; 3377 if (chunk[isSourceNode]) { 3378 chunk.walk(aFn); 3379 } else if (chunk !== "") { 3380 aFn(chunk, { source: this.source, 3381 line: this.line, 3382 column: this.column, 3383 name: this.name }); 3384 } 3385 } 3386 } 3387 3388 /** 3389 * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between 3390 * each of `this.children`. 3391 * 3392 * @param aSep The separator. 3393 */ 3394 join(aSep) { 3395 let newChildren; 3396 let i; 3397 const len = this.children.length; 3398 if (len > 0) { 3399 newChildren = []; 3400 for (i = 0; i < len - 1; i++) { 3401 newChildren.push(this.children[i]); 3402 newChildren.push(aSep); 3403 } 3404 newChildren.push(this.children[i]); 3405 this.children = newChildren; 3406 } 3407 return this; 3408 } 3409 3410 /** 3411 * Call String.prototype.replace on the very right-most source snippet. Useful 3412 * for trimming whitespace from the end of a source node, etc. 3413 * 3414 * @param aPattern The pattern to replace. 3415 * @param aReplacement The thing to replace the pattern with. 3416 */ 3417 replaceRight(aPattern, aReplacement) { 3418 const lastChild = this.children[this.children.length - 1]; 3419 if (lastChild[isSourceNode]) { 3420 lastChild.replaceRight(aPattern, aReplacement); 3421 } else if (typeof lastChild === "string") { 3422 this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); 3423 } else { 3424 this.children.push("".replace(aPattern, aReplacement)); 3425 } 3426 return this; 3427 } 3428 3429 /** 3430 * Set the source content for a source file. This will be added to the SourceMapGenerator 3431 * in the sourcesContent field. 3432 * 3433 * @param aSourceFile The filename of the source file 3434 * @param aSourceContent The content of the source file 3435 */ 3436 setSourceContent(aSourceFile, aSourceContent) { 3437 this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; 3438 } 3439 3440 /** 3441 * Walk over the tree of SourceNodes. The walking function is called for each 3442 * source file content and is passed the filename and source content. 3443 * 3444 * @param aFn The traversal function. 3445 */ 3446 walkSourceContents(aFn) { 3447 for (let i = 0, len = this.children.length; i < len; i++) { 3448 if (this.children[i][isSourceNode]) { 3449 this.children[i].walkSourceContents(aFn); 3450 } 3451 } 3452 3453 const sources = Object.keys(this.sourceContents); 3454 for (let i = 0, len = sources.length; i < len; i++) { 3455 aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); 3456 } 3457 } 3458 3459 /** 3460 * Return the string representation of this source node. Walks over the tree 3461 * and concatenates all the various snippets together to one string. 3462 */ 3463 toString() { 3464 let str = ""; 3465 this.walk(function(chunk) { 3466 str += chunk; 3467 }); 3468 return str; 3469 } 3470 3471 /** 3472 * Returns the string representation of this source node along with a source 3473 * map. 3474 */ 3475 toStringWithSourceMap(aArgs) { 3476 const generated = { 3477 code: "", 3478 line: 1, 3479 column: 0 3480 }; 3481 const map = new SourceMapGenerator(aArgs); 3482 let sourceMappingActive = false; 3483 let lastOriginalSource = null; 3484 let lastOriginalLine = null; 3485 let lastOriginalColumn = null; 3486 let lastOriginalName = null; 3487 this.walk(function(chunk, original) { 3488 generated.code += chunk; 3489 if (original.source !== null 3490 && original.line !== null 3491 && original.column !== null) { 3492 if (lastOriginalSource !== original.source 3493 || lastOriginalLine !== original.line 3494 || lastOriginalColumn !== original.column 3495 || lastOriginalName !== original.name) { 3496 map.addMapping({ 3497 source: original.source, 3498 original: { 3499 line: original.line, 3500 column: original.column 3501 }, 3502 generated: { 3503 line: generated.line, 3504 column: generated.column 3505 }, 3506 name: original.name 3507 }); 3508 } 3509 lastOriginalSource = original.source; 3510 lastOriginalLine = original.line; 3511 lastOriginalColumn = original.column; 3512 lastOriginalName = original.name; 3513 sourceMappingActive = true; 3514 } else if (sourceMappingActive) { 3515 map.addMapping({ 3516 generated: { 3517 line: generated.line, 3518 column: generated.column 3519 } 3520 }); 3521 lastOriginalSource = null; 3522 sourceMappingActive = false; 3523 } 3524 for (let idx = 0, length = chunk.length; idx < length; idx++) { 3525 if (chunk.charCodeAt(idx) === NEWLINE_CODE) { 3526 generated.line++; 3527 generated.column = 0; 3528 // Mappings end at eol 3529 if (idx + 1 === length) { 3530 lastOriginalSource = null; 3531 sourceMappingActive = false; 3532 } else if (sourceMappingActive) { 3533 map.addMapping({ 3534 source: original.source, 3535 original: { 3536 line: original.line, 3537 column: original.column 3538 }, 3539 generated: { 3540 line: generated.line, 3541 column: generated.column 3542 }, 3543 name: original.name 3544 }); 3545 } 3546 } else { 3547 generated.column++; 3548 } 3549 } 3550 }); 3551 this.walkSourceContents(function(sourceFile, sourceContent) { 3552 map.setSourceContent(sourceFile, sourceContent); 3553 }); 3554 3555 return { code: generated.code, map }; 3556 } 3557 } 3558 3559 sourceNode.SourceNode = SourceNode; 3560 return sourceNode; 3561 } 3562 3563 var hasRequiredSourceMap; 3564 3565 function requireSourceMap () { 3566 if (hasRequiredSourceMap) return sourceMap$1; 3567 hasRequiredSourceMap = 1; 3568 sourceMap$1.SourceMapGenerator = requireSourceMapGenerator().SourceMapGenerator; 3569 sourceMap$1.SourceMapConsumer = requireSourceMapConsumer().SourceMapConsumer; 3570 sourceMap$1.SourceNode = requireSourceNode().SourceNode; 3571 return sourceMap$1; 3572 } 3573 3574 var workerUtils = {exports: {}}; 3575 3576 var hasRequiredWorkerUtils; 3577 3578 function requireWorkerUtils () { 3579 if (hasRequiredWorkerUtils) return workerUtils.exports; 3580 hasRequiredWorkerUtils = 1; 3581 (function (module) { 3582 3583 class WorkerDispatcher { 3584 #msgId = 1; 3585 #worker = null; 3586 // Map of message ids -> promise resolution functions, for dispatching worker responses 3587 #pendingCalls = new Map(); 3588 #url = ""; 3589 3590 constructor(url) { 3591 this.#url = url; 3592 } 3593 3594 start() { 3595 // When running in debugger jest test, we don't have access to ChromeWorker 3596 if (typeof ChromeWorker == "function") { 3597 this.#worker = new ChromeWorker(this.#url); 3598 } else { 3599 this.#worker = new Worker(this.#url); 3600 } 3601 this.#worker.onerror = err => { 3602 console.error(`Error in worker ${this.#url}`, err.message); 3603 }; 3604 this.#worker.addEventListener("message", this.#onMessage); 3605 } 3606 3607 stop() { 3608 if (!this.#worker) { 3609 return; 3610 } 3611 3612 this.#worker.removeEventListener("message", this.#onMessage); 3613 this.#worker.terminate(); 3614 this.#worker = null; 3615 this.#pendingCalls.clear(); 3616 } 3617 3618 task(method, { queue = false } = {}) { 3619 const calls = []; 3620 const push = args => { 3621 return new Promise((resolve, reject) => { 3622 if (queue && calls.length === 0) { 3623 Promise.resolve().then(flush); 3624 } 3625 3626 calls.push({ args, resolve, reject }); 3627 3628 if (!queue) { 3629 flush(); 3630 } 3631 }); 3632 }; 3633 3634 const flush = () => { 3635 const items = calls.slice(); 3636 calls.length = 0; 3637 3638 if (!this.#worker) { 3639 this.start(); 3640 } 3641 3642 const id = this.#msgId++; 3643 this.#worker.postMessage({ 3644 id, 3645 method, 3646 calls: items.map(item => item.args), 3647 }); 3648 3649 this.#pendingCalls.set(id, items); 3650 }; 3651 3652 return (...args) => push(args); 3653 } 3654 3655 invoke(method, ...args) { 3656 return this.task(method)(...args); 3657 } 3658 3659 #onMessage = ({ data: result }) => { 3660 const items = this.#pendingCalls.get(result.id); 3661 this.#pendingCalls.delete(result.id); 3662 if (!items) { 3663 return; 3664 } 3665 3666 if (!this.#worker) { 3667 return; 3668 } 3669 3670 result.results.forEach((resultData, i) => { 3671 const { resolve, reject } = items[i]; 3672 3673 if (resultData.error) { 3674 const err = new Error(resultData.message); 3675 err.metadata = resultData.metadata; 3676 reject(err); 3677 } else { 3678 resolve(resultData.response); 3679 } 3680 }); 3681 }; 3682 } 3683 3684 function workerHandler(publicInterface) { 3685 return function (msg) { 3686 const { id, method, calls } = msg.data; 3687 3688 Promise.all( 3689 calls.map(args => { 3690 try { 3691 const response = publicInterface[method].apply(undefined, args); 3692 if (response instanceof Promise) { 3693 return response.then( 3694 val => ({ response: val }), 3695 err => asErrorMessage(err) 3696 ); 3697 } 3698 return { response }; 3699 } catch (error) { 3700 return asErrorMessage(error); 3701 } 3702 }) 3703 ).then(results => { 3704 globalThis.postMessage({ id, results }); 3705 }); 3706 }; 3707 } 3708 3709 function asErrorMessage(error) { 3710 if (typeof error === "object" && error && "message" in error) { 3711 // Error can't be sent via postMessage, so be sure to convert to 3712 // string. 3713 return { 3714 error: true, 3715 message: 3716 error.message + 3717 (error.stack ? "\nStack in the worker:" + error.stack : ""), 3718 metadata: error.metadata, 3719 }; 3720 } 3721 3722 return { 3723 error: true, 3724 message: error == null ? error : error.toString(), 3725 metadata: undefined, 3726 }; 3727 } 3728 3729 // Might be loaded within a worker thread where `module` isn't available. 3730 { 3731 module.exports = { 3732 WorkerDispatcher, 3733 workerHandler, 3734 }; 3735 } 3736 } (workerUtils)); 3737 return workerUtils.exports; 3738 } 3739 3740 var workerUtilsExports = requireWorkerUtils(); 3741 3742 var acorn$1 = {exports: {}}; 3743 3744 var hasRequiredAcorn; 3745 3746 function requireAcorn () { 3747 if (hasRequiredAcorn) return acorn$1.exports; 3748 hasRequiredAcorn = 1; 3749 (function (module, exports) { 3750 (function (global, factory) { 3751 factory(exports) ; 3752 })(commonjsGlobal, (function (exports) { 3753 // This file was generated. Do not modify manually! 3754 var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 81, 2, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 9, 5351, 0, 7, 14, 13835, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 983, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; 3755 3756 // This file was generated. Do not modify manually! 3757 var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938, 6, 4191]; 3758 3759 // This file was generated. Do not modify manually! 3760 var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; 3761 3762 // This file was generated. Do not modify manually! 3763 var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; 3764 3765 // These are a run-length and offset encoded representation of the 3766 3767 // Reserved word lists for various dialects of the language 3768 3769 var reservedWords = { 3770 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 3771 5: "class enum extends super const export import", 3772 6: "enum", 3773 strict: "implements interface let package private protected public static yield", 3774 strictBind: "eval arguments" 3775 }; 3776 3777 // And the keywords 3778 3779 var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; 3780 3781 var keywords$1 = { 3782 5: ecma5AndLessKeywords, 3783 "5module": ecma5AndLessKeywords + " export import", 3784 6: ecma5AndLessKeywords + " const class extends export import super" 3785 }; 3786 3787 var keywordRelationalOperator = /^in(stanceof)?$/; 3788 3789 // ## Character categories 3790 3791 var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); 3792 var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); 3793 3794 // This has a complexity linear to the value of the code. The 3795 // assumption is that looking up astral identifier characters is 3796 // rare. 3797 function isInAstralSet(code, set) { 3798 var pos = 0x10000; 3799 for (var i = 0; i < set.length; i += 2) { 3800 pos += set[i]; 3801 if (pos > code) { return false } 3802 pos += set[i + 1]; 3803 if (pos >= code) { return true } 3804 } 3805 return false 3806 } 3807 3808 // Test whether a given character code starts an identifier. 3809 3810 function isIdentifierStart(code, astral) { 3811 if (code < 65) { return code === 36 } 3812 if (code < 91) { return true } 3813 if (code < 97) { return code === 95 } 3814 if (code < 123) { return true } 3815 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } 3816 if (astral === false) { return false } 3817 return isInAstralSet(code, astralIdentifierStartCodes) 3818 } 3819 3820 // Test whether a given character is part of an identifier. 3821 3822 function isIdentifierChar(code, astral) { 3823 if (code < 48) { return code === 36 } 3824 if (code < 58) { return true } 3825 if (code < 65) { return false } 3826 if (code < 91) { return true } 3827 if (code < 97) { return code === 95 } 3828 if (code < 123) { return true } 3829 if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } 3830 if (astral === false) { return false } 3831 return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) 3832 } 3833 3834 // ## Token types 3835 3836 // The assignment of fine-grained, information-carrying type objects 3837 // allows the tokenizer to store the information it has about a 3838 // token in a way that is very cheap for the parser to look up. 3839 3840 // All token type variables start with an underscore, to make them 3841 // easy to recognize. 3842 3843 // The `beforeExpr` property is used to disambiguate between regular 3844 // expressions and divisions. It is set on all token types that can 3845 // be followed by an expression (thus, a slash after them would be a 3846 // regular expression). 3847 // 3848 // The `startsExpr` property is used to check if the token ends a 3849 // `yield` expression. It is set on all token types that either can 3850 // directly start an expression (like a quotation mark) or can 3851 // continue an expression (like the body of a string). 3852 // 3853 // `isLoop` marks a keyword as starting a loop, which is important 3854 // to know when parsing a label, in order to allow or disallow 3855 // continue jumps to that label. 3856 3857 var TokenType = function TokenType(label, conf) { 3858 if ( conf === void 0 ) conf = {}; 3859 3860 this.label = label; 3861 this.keyword = conf.keyword; 3862 this.beforeExpr = !!conf.beforeExpr; 3863 this.startsExpr = !!conf.startsExpr; 3864 this.isLoop = !!conf.isLoop; 3865 this.isAssign = !!conf.isAssign; 3866 this.prefix = !!conf.prefix; 3867 this.postfix = !!conf.postfix; 3868 this.binop = conf.binop || null; 3869 this.updateContext = null; 3870 }; 3871 3872 function binop(name, prec) { 3873 return new TokenType(name, {beforeExpr: true, binop: prec}) 3874 } 3875 var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; 3876 3877 // Map keyword names to token types. 3878 3879 var keywords = {}; 3880 3881 // Succinct definitions of keyword token types 3882 function kw(name, options) { 3883 if ( options === void 0 ) options = {}; 3884 3885 options.keyword = name; 3886 return keywords[name] = new TokenType(name, options) 3887 } 3888 3889 var types$1 = { 3890 num: new TokenType("num", startsExpr), 3891 regexp: new TokenType("regexp", startsExpr), 3892 string: new TokenType("string", startsExpr), 3893 name: new TokenType("name", startsExpr), 3894 privateId: new TokenType("privateId", startsExpr), 3895 eof: new TokenType("eof"), 3896 3897 // Punctuation token types. 3898 bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), 3899 bracketR: new TokenType("]"), 3900 braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), 3901 braceR: new TokenType("}"), 3902 parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), 3903 parenR: new TokenType(")"), 3904 comma: new TokenType(",", beforeExpr), 3905 semi: new TokenType(";", beforeExpr), 3906 colon: new TokenType(":", beforeExpr), 3907 dot: new TokenType("."), 3908 question: new TokenType("?", beforeExpr), 3909 questionDot: new TokenType("?."), 3910 arrow: new TokenType("=>", beforeExpr), 3911 template: new TokenType("template"), 3912 invalidTemplate: new TokenType("invalidTemplate"), 3913 ellipsis: new TokenType("...", beforeExpr), 3914 backQuote: new TokenType("`", startsExpr), 3915 dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), 3916 3917 // Operators. These carry several kinds of properties to help the 3918 // parser use them properly (the presence of these properties is 3919 // what categorizes them as operators). 3920 // 3921 // `binop`, when present, specifies that this operator is a binary 3922 // operator, and will refer to its precedence. 3923 // 3924 // `prefix` and `postfix` mark the operator as a prefix or postfix 3925 // unary operator. 3926 // 3927 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as 3928 // binary operators with a very low precedence, that should result 3929 // in AssignmentExpression nodes. 3930 3931 eq: new TokenType("=", {beforeExpr: true, isAssign: true}), 3932 assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), 3933 incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), 3934 prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), 3935 logicalOR: binop("||", 1), 3936 logicalAND: binop("&&", 2), 3937 bitwiseOR: binop("|", 3), 3938 bitwiseXOR: binop("^", 4), 3939 bitwiseAND: binop("&", 5), 3940 equality: binop("==/!=/===/!==", 6), 3941 relational: binop("</>/<=/>=", 7), 3942 bitShift: binop("<</>>/>>>", 8), 3943 plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), 3944 modulo: binop("%", 10), 3945 star: binop("*", 10), 3946 slash: binop("/", 10), 3947 starstar: new TokenType("**", {beforeExpr: true}), 3948 coalesce: binop("??", 1), 3949 3950 // Keyword token types. 3951 _break: kw("break"), 3952 _case: kw("case", beforeExpr), 3953 _catch: kw("catch"), 3954 _continue: kw("continue"), 3955 _debugger: kw("debugger"), 3956 _default: kw("default", beforeExpr), 3957 _do: kw("do", {isLoop: true, beforeExpr: true}), 3958 _else: kw("else", beforeExpr), 3959 _finally: kw("finally"), 3960 _for: kw("for", {isLoop: true}), 3961 _function: kw("function", startsExpr), 3962 _if: kw("if"), 3963 _return: kw("return", beforeExpr), 3964 _switch: kw("switch"), 3965 _throw: kw("throw", beforeExpr), 3966 _try: kw("try"), 3967 _var: kw("var"), 3968 _const: kw("const"), 3969 _while: kw("while", {isLoop: true}), 3970 _with: kw("with"), 3971 _new: kw("new", {beforeExpr: true, startsExpr: true}), 3972 _this: kw("this", startsExpr), 3973 _super: kw("super", startsExpr), 3974 _class: kw("class", startsExpr), 3975 _extends: kw("extends", beforeExpr), 3976 _export: kw("export"), 3977 _import: kw("import", startsExpr), 3978 _null: kw("null", startsExpr), 3979 _true: kw("true", startsExpr), 3980 _false: kw("false", startsExpr), 3981 _in: kw("in", {beforeExpr: true, binop: 7}), 3982 _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), 3983 _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), 3984 _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), 3985 _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) 3986 }; 3987 3988 // Matches a whole line break (where CRLF is considered a single 3989 // line break). Used to count lines. 3990 3991 var lineBreak = /\r\n?|\n|\u2028|\u2029/; 3992 var lineBreakG = new RegExp(lineBreak.source, "g"); 3993 3994 function isNewLine(code) { 3995 return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 3996 } 3997 3998 function nextLineBreak(code, from, end) { 3999 if ( end === void 0 ) end = code.length; 4000 4001 for (var i = from; i < end; i++) { 4002 var next = code.charCodeAt(i); 4003 if (isNewLine(next)) 4004 { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 } 4005 } 4006 return -1 4007 } 4008 4009 var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; 4010 4011 var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; 4012 4013 var ref = Object.prototype; 4014 var hasOwnProperty = ref.hasOwnProperty; 4015 var toString = ref.toString; 4016 4017 var hasOwn = Object.hasOwn || (function (obj, propName) { return ( 4018 hasOwnProperty.call(obj, propName) 4019 ); }); 4020 4021 var isArray = Array.isArray || (function (obj) { return ( 4022 toString.call(obj) === "[object Array]" 4023 ); }); 4024 4025 function wordsRegexp(words) { 4026 return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") 4027 } 4028 4029 function codePointToString(code) { 4030 // UTF-16 Decoding 4031 if (code <= 0xFFFF) { return String.fromCharCode(code) } 4032 code -= 0x10000; 4033 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) 4034 } 4035 4036 var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/; 4037 4038 // These are used when `options.locations` is on, for the 4039 // `startLoc` and `endLoc` properties. 4040 4041 var Position = function Position(line, col) { 4042 this.line = line; 4043 this.column = col; 4044 }; 4045 4046 Position.prototype.offset = function offset (n) { 4047 return new Position(this.line, this.column + n) 4048 }; 4049 4050 var SourceLocation = function SourceLocation(p, start, end) { 4051 this.start = start; 4052 this.end = end; 4053 if (p.sourceFile !== null) { this.source = p.sourceFile; } 4054 }; 4055 4056 // The `getLineInfo` function is mostly useful when the 4057 // `locations` option is off (for performance reasons) and you 4058 // want to find the line/column position for a given character 4059 // offset. `input` should be the code string that the offset refers 4060 // into. 4061 4062 function getLineInfo(input, offset) { 4063 for (var line = 1, cur = 0;;) { 4064 var nextBreak = nextLineBreak(input, cur, offset); 4065 if (nextBreak < 0) { return new Position(line, offset - cur) } 4066 ++line; 4067 cur = nextBreak; 4068 } 4069 } 4070 4071 // A second argument must be given to configure the parser process. 4072 // These options are recognized (only `ecmaVersion` is required): 4073 4074 var defaultOptions = { 4075 // `ecmaVersion` indicates the ECMAScript version to parse. Must be 4076 // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 4077 // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` 4078 // (the latest version the library supports). This influences 4079 // support for strict mode, the set of reserved words, and support 4080 // for new syntax features. 4081 ecmaVersion: null, 4082 // `sourceType` indicates the mode the code should be parsed in. 4083 // Can be either `"script"` or `"module"`. This influences global 4084 // strict mode and parsing of `import` and `export` declarations. 4085 sourceType: "script", 4086 // `onInsertedSemicolon` can be a callback that will be called 4087 // when a semicolon is automatically inserted. It will be passed 4088 // the position of the comma as an offset, and if `locations` is 4089 // enabled, it is given the location as a `{line, column}` object 4090 // as second argument. 4091 onInsertedSemicolon: null, 4092 // `onTrailingComma` is similar to `onInsertedSemicolon`, but for 4093 // trailing commas. 4094 onTrailingComma: null, 4095 // By default, reserved words are only enforced if ecmaVersion >= 5. 4096 // Set `allowReserved` to a boolean value to explicitly turn this on 4097 // an off. When this option has the value "never", reserved words 4098 // and keywords can also not be used as property names. 4099 allowReserved: null, 4100 // When enabled, a return at the top level is not considered an 4101 // error. 4102 allowReturnOutsideFunction: false, 4103 // When enabled, import/export statements are not constrained to 4104 // appearing at the top of the program, and an import.meta expression 4105 // in a script isn't considered an error. 4106 allowImportExportEverywhere: false, 4107 // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. 4108 // When enabled, await identifiers are allowed to appear at the top-level scope, 4109 // but they are still not allowed in non-async functions. 4110 allowAwaitOutsideFunction: null, 4111 // When enabled, super identifiers are not constrained to 4112 // appearing in methods and do not raise an error when they appear elsewhere. 4113 allowSuperOutsideMethod: null, 4114 // When enabled, hashbang directive in the beginning of file is 4115 // allowed and treated as a line comment. Enabled by default when 4116 // `ecmaVersion` >= 2023. 4117 allowHashBang: false, 4118 // When `locations` is on, `loc` properties holding objects with 4119 // `start` and `end` properties in `{line, column}` form (with 4120 // line being 1-based and column 0-based) will be attached to the 4121 // nodes. 4122 locations: false, 4123 // A function can be passed as `onToken` option, which will 4124 // cause Acorn to call that function with object in the same 4125 // format as tokens returned from `tokenizer().getToken()`. Note 4126 // that you are not allowed to call the parser from the 4127 // callback—that will corrupt its internal state. 4128 onToken: null, 4129 // A function can be passed as `onComment` option, which will 4130 // cause Acorn to call that function with `(block, text, start, 4131 // end)` parameters whenever a comment is skipped. `block` is a 4132 // boolean indicating whether this is a block (`/* */`) comment, 4133 // `text` is the content of the comment, and `start` and `end` are 4134 // character offsets that denote the start and end of the comment. 4135 // When the `locations` option is on, two more parameters are 4136 // passed, the full `{line, column}` locations of the start and 4137 // end of the comments. Note that you are not allowed to call the 4138 // parser from the callback—that will corrupt its internal state. 4139 onComment: null, 4140 // Nodes have their start and end characters offsets recorded in 4141 // `start` and `end` properties (directly on the node, rather than 4142 // the `loc` object, which holds line/column data. To also add a 4143 // [semi-standardized][range] `range` property holding a `[start, 4144 // end]` array with the same numbers, set the `ranges` option to 4145 // `true`. 4146 // 4147 // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 4148 ranges: false, 4149 // It is possible to parse multiple files into a single AST by 4150 // passing the tree produced by parsing the first file as 4151 // `program` option in subsequent parses. This will add the 4152 // toplevel forms of the parsed file to the `Program` (top) node 4153 // of an existing parse tree. 4154 program: null, 4155 // When `locations` is on, you can pass this to record the source 4156 // file in every node's `loc` object. 4157 sourceFile: null, 4158 // This value, if given, is stored in every node, whether 4159 // `locations` is on or off. 4160 directSourceFile: null, 4161 // When enabled, parenthesized expressions are represented by 4162 // (non-standard) ParenthesizedExpression nodes 4163 preserveParens: false 4164 }; 4165 4166 // Interpret and default an options object 4167 4168 var warnedAboutEcmaVersion = false; 4169 4170 function getOptions(opts) { 4171 var options = {}; 4172 4173 for (var opt in defaultOptions) 4174 { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; } 4175 4176 if (options.ecmaVersion === "latest") { 4177 options.ecmaVersion = 1e8; 4178 } else if (options.ecmaVersion == null) { 4179 if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) { 4180 warnedAboutEcmaVersion = true; 4181 console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future."); 4182 } 4183 options.ecmaVersion = 11; 4184 } else if (options.ecmaVersion >= 2015) { 4185 options.ecmaVersion -= 2009; 4186 } 4187 4188 if (options.allowReserved == null) 4189 { options.allowReserved = options.ecmaVersion < 5; } 4190 4191 if (!opts || opts.allowHashBang == null) 4192 { options.allowHashBang = options.ecmaVersion >= 14; } 4193 4194 if (isArray(options.onToken)) { 4195 var tokens = options.onToken; 4196 options.onToken = function (token) { return tokens.push(token); }; 4197 } 4198 if (isArray(options.onComment)) 4199 { options.onComment = pushComment(options, options.onComment); } 4200 4201 return options 4202 } 4203 4204 function pushComment(options, array) { 4205 return function(block, text, start, end, startLoc, endLoc) { 4206 var comment = { 4207 type: block ? "Block" : "Line", 4208 value: text, 4209 start: start, 4210 end: end 4211 }; 4212 if (options.locations) 4213 { comment.loc = new SourceLocation(this, startLoc, endLoc); } 4214 if (options.ranges) 4215 { comment.range = [start, end]; } 4216 array.push(comment); 4217 } 4218 } 4219 4220 // Each scope gets a bitset that may contain these flags 4221 var 4222 SCOPE_TOP = 1, 4223 SCOPE_FUNCTION = 2, 4224 SCOPE_ASYNC = 4, 4225 SCOPE_GENERATOR = 8, 4226 SCOPE_ARROW = 16, 4227 SCOPE_SIMPLE_CATCH = 32, 4228 SCOPE_SUPER = 64, 4229 SCOPE_DIRECT_SUPER = 128, 4230 SCOPE_CLASS_STATIC_BLOCK = 256, 4231 SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK; 4232 4233 function functionFlags(async, generator) { 4234 return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) 4235 } 4236 4237 // Used in checkLVal* and declareName to determine the type of a binding 4238 var 4239 BIND_NONE = 0, // Not a binding 4240 BIND_VAR = 1, // Var-style binding 4241 BIND_LEXICAL = 2, // Let- or const-style binding 4242 BIND_FUNCTION = 3, // Function declaration 4243 BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding 4244 BIND_OUTSIDE = 5; // Special case for function names as bound inside the function 4245 4246 var Parser = function Parser(options, input, startPos) { 4247 this.options = options = getOptions(options); 4248 this.sourceFile = options.sourceFile; 4249 this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); 4250 var reserved = ""; 4251 if (options.allowReserved !== true) { 4252 reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]; 4253 if (options.sourceType === "module") { reserved += " await"; } 4254 } 4255 this.reservedWords = wordsRegexp(reserved); 4256 var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; 4257 this.reservedWordsStrict = wordsRegexp(reservedStrict); 4258 this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); 4259 this.input = String(input); 4260 4261 // Used to signal to callers of `readWord1` whether the word 4262 // contained any escape sequences. This is needed because words with 4263 // escape sequences must not be interpreted as keywords. 4264 this.containsEsc = false; 4265 4266 // Set up token state 4267 4268 // The current position of the tokenizer in the input. 4269 if (startPos) { 4270 this.pos = startPos; 4271 this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; 4272 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; 4273 } else { 4274 this.pos = this.lineStart = 0; 4275 this.curLine = 1; 4276 } 4277 4278 // Properties of the current token: 4279 // Its type 4280 this.type = types$1.eof; 4281 // For tokens that include more information than their type, the value 4282 this.value = null; 4283 // Its start and end offset 4284 this.start = this.end = this.pos; 4285 // And, if locations are used, the {line, column} object 4286 // corresponding to those offsets 4287 this.startLoc = this.endLoc = this.curPosition(); 4288 4289 // Position information for the previous token 4290 this.lastTokEndLoc = this.lastTokStartLoc = null; 4291 this.lastTokStart = this.lastTokEnd = this.pos; 4292 4293 // The context stack is used to superficially track syntactic 4294 // context to predict whether a regular expression is allowed in a 4295 // given position. 4296 this.context = this.initialContext(); 4297 this.exprAllowed = true; 4298 4299 // Figure out if it's a module code. 4300 this.inModule = options.sourceType === "module"; 4301 this.strict = this.inModule || this.strictDirective(this.pos); 4302 4303 // Used to signify the start of a potential arrow function 4304 this.potentialArrowAt = -1; 4305 this.potentialArrowInForAwait = false; 4306 4307 // Positions to delayed-check that yield/await does not exist in default parameters. 4308 this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; 4309 // Labels in scope. 4310 this.labels = []; 4311 // Thus-far undefined exports. 4312 this.undefinedExports = Object.create(null); 4313 4314 // If enabled, skip leading hashbang line. 4315 if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") 4316 { this.skipLineComment(2); } 4317 4318 // Scope tracking for duplicate variable names (see scope.js) 4319 this.scopeStack = []; 4320 this.enterScope(SCOPE_TOP); 4321 4322 // For RegExp validation 4323 this.regexpState = null; 4324 4325 // The stack of private names. 4326 // Each element has two properties: 'declared' and 'used'. 4327 // When it exited from the outermost class definition, all used private names must be declared. 4328 this.privateNameStack = []; 4329 }; 4330 4331 var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } }; 4332 4333 Parser.prototype.parse = function parse () { 4334 var node = this.options.program || this.startNode(); 4335 this.nextToken(); 4336 return this.parseTopLevel(node) 4337 }; 4338 4339 prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; 4340 4341 prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentVarScope().inClassFieldInit }; 4342 4343 prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 && !this.currentVarScope().inClassFieldInit }; 4344 4345 prototypeAccessors.canAwait.get = function () { 4346 for (var i = this.scopeStack.length - 1; i >= 0; i--) { 4347 var scope = this.scopeStack[i]; 4348 if (scope.inClassFieldInit || scope.flags & SCOPE_CLASS_STATIC_BLOCK) { return false } 4349 if (scope.flags & SCOPE_FUNCTION) { return (scope.flags & SCOPE_ASYNC) > 0 } 4350 } 4351 return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction 4352 }; 4353 4354 prototypeAccessors.allowSuper.get = function () { 4355 var ref = this.currentThisScope(); 4356 var flags = ref.flags; 4357 var inClassFieldInit = ref.inClassFieldInit; 4358 return (flags & SCOPE_SUPER) > 0 || inClassFieldInit || this.options.allowSuperOutsideMethod 4359 }; 4360 4361 prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; 4362 4363 prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; 4364 4365 prototypeAccessors.allowNewDotTarget.get = function () { 4366 var ref = this.currentThisScope(); 4367 var flags = ref.flags; 4368 var inClassFieldInit = ref.inClassFieldInit; 4369 return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || inClassFieldInit 4370 }; 4371 4372 prototypeAccessors.inClassStaticBlock.get = function () { 4373 return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0 4374 }; 4375 4376 Parser.extend = function extend () { 4377 var plugins = [], len = arguments.length; 4378 while ( len-- ) plugins[ len ] = arguments[ len ]; 4379 4380 var cls = this; 4381 for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } 4382 return cls 4383 }; 4384 4385 Parser.parse = function parse (input, options) { 4386 return new this(options, input).parse() 4387 }; 4388 4389 Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { 4390 var parser = new this(options, input, pos); 4391 parser.nextToken(); 4392 return parser.parseExpression() 4393 }; 4394 4395 Parser.tokenizer = function tokenizer (input, options) { 4396 return new this(options, input) 4397 }; 4398 4399 Object.defineProperties( Parser.prototype, prototypeAccessors ); 4400 4401 var pp$9 = Parser.prototype; 4402 4403 // ## Parser utilities 4404 4405 var literal = /^(?:'((?:\\.|[^'\\])*?)'|"((?:\\.|[^"\\])*?)")/; 4406 pp$9.strictDirective = function(start) { 4407 if (this.options.ecmaVersion < 5) { return false } 4408 for (;;) { 4409 // Try to find string literal. 4410 skipWhiteSpace.lastIndex = start; 4411 start += skipWhiteSpace.exec(this.input)[0].length; 4412 var match = literal.exec(this.input.slice(start)); 4413 if (!match) { return false } 4414 if ((match[1] || match[2]) === "use strict") { 4415 skipWhiteSpace.lastIndex = start + match[0].length; 4416 var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; 4417 var next = this.input.charAt(end); 4418 return next === ";" || next === "}" || 4419 (lineBreak.test(spaceAfter[0]) && 4420 !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) 4421 } 4422 start += match[0].length; 4423 4424 // Skip semicolon, if any. 4425 skipWhiteSpace.lastIndex = start; 4426 start += skipWhiteSpace.exec(this.input)[0].length; 4427 if (this.input[start] === ";") 4428 { start++; } 4429 } 4430 }; 4431 4432 // Predicate that tests whether the next token is of the given 4433 // type, and if yes, consumes it as a side effect. 4434 4435 pp$9.eat = function(type) { 4436 if (this.type === type) { 4437 this.next(); 4438 return true 4439 } else { 4440 return false 4441 } 4442 }; 4443 4444 // Tests whether parsed token is a contextual keyword. 4445 4446 pp$9.isContextual = function(name) { 4447 return this.type === types$1.name && this.value === name && !this.containsEsc 4448 }; 4449 4450 // Consumes contextual keyword if possible. 4451 4452 pp$9.eatContextual = function(name) { 4453 if (!this.isContextual(name)) { return false } 4454 this.next(); 4455 return true 4456 }; 4457 4458 // Asserts that following token is given contextual keyword. 4459 4460 pp$9.expectContextual = function(name) { 4461 if (!this.eatContextual(name)) { this.unexpected(); } 4462 }; 4463 4464 // Test whether a semicolon can be inserted at the current position. 4465 4466 pp$9.canInsertSemicolon = function() { 4467 return this.type === types$1.eof || 4468 this.type === types$1.braceR || 4469 lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) 4470 }; 4471 4472 pp$9.insertSemicolon = function() { 4473 if (this.canInsertSemicolon()) { 4474 if (this.options.onInsertedSemicolon) 4475 { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } 4476 return true 4477 } 4478 }; 4479 4480 // Consume a semicolon, or, failing that, see if we are allowed to 4481 // pretend that there is a semicolon at this position. 4482 4483 pp$9.semicolon = function() { 4484 if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); } 4485 }; 4486 4487 pp$9.afterTrailingComma = function(tokType, notNext) { 4488 if (this.type === tokType) { 4489 if (this.options.onTrailingComma) 4490 { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } 4491 if (!notNext) 4492 { this.next(); } 4493 return true 4494 } 4495 }; 4496 4497 // Expect a token of a given type. If found, consume it, otherwise, 4498 // raise an unexpected token error. 4499 4500 pp$9.expect = function(type) { 4501 this.eat(type) || this.unexpected(); 4502 }; 4503 4504 // Raise an unexpected token error. 4505 4506 pp$9.unexpected = function(pos) { 4507 this.raise(pos != null ? pos : this.start, "Unexpected token"); 4508 }; 4509 4510 var DestructuringErrors = function DestructuringErrors() { 4511 this.shorthandAssign = 4512 this.trailingComma = 4513 this.parenthesizedAssign = 4514 this.parenthesizedBind = 4515 this.doubleProto = 4516 -1; 4517 }; 4518 4519 pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) { 4520 if (!refDestructuringErrors) { return } 4521 if (refDestructuringErrors.trailingComma > -1) 4522 { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } 4523 var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; 4524 if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); } 4525 }; 4526 4527 pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) { 4528 if (!refDestructuringErrors) { return false } 4529 var shorthandAssign = refDestructuringErrors.shorthandAssign; 4530 var doubleProto = refDestructuringErrors.doubleProto; 4531 if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } 4532 if (shorthandAssign >= 0) 4533 { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } 4534 if (doubleProto >= 0) 4535 { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } 4536 }; 4537 4538 pp$9.checkYieldAwaitInDefaultParams = function() { 4539 if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) 4540 { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } 4541 if (this.awaitPos) 4542 { this.raise(this.awaitPos, "Await expression cannot be a default value"); } 4543 }; 4544 4545 pp$9.isSimpleAssignTarget = function(expr) { 4546 if (expr.type === "ParenthesizedExpression") 4547 { return this.isSimpleAssignTarget(expr.expression) } 4548 return expr.type === "Identifier" || expr.type === "MemberExpression" 4549 }; 4550 4551 var pp$8 = Parser.prototype; 4552 4553 // ### Statement parsing 4554 4555 // Parse a program. Initializes the parser, reads any number of 4556 // statements, and wraps them in a Program node. Optionally takes a 4557 // `program` argument. If present, the statements will be appended 4558 // to its body instead of creating a new node. 4559 4560 pp$8.parseTopLevel = function(node) { 4561 var exports = Object.create(null); 4562 if (!node.body) { node.body = []; } 4563 while (this.type !== types$1.eof) { 4564 var stmt = this.parseStatement(null, true, exports); 4565 node.body.push(stmt); 4566 } 4567 if (this.inModule) 4568 { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) 4569 { 4570 var name = list[i]; 4571 4572 this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); 4573 } } 4574 this.adaptDirectivePrologue(node.body); 4575 this.next(); 4576 node.sourceType = this.options.sourceType; 4577 return this.finishNode(node, "Program") 4578 }; 4579 4580 var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; 4581 4582 pp$8.isLet = function(context) { 4583 if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } 4584 skipWhiteSpace.lastIndex = this.pos; 4585 var skip = skipWhiteSpace.exec(this.input); 4586 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); 4587 // For ambiguous cases, determine if a LexicalDeclaration (or only a 4588 // Statement) is allowed here. If context is not empty then only a Statement 4589 // is allowed. However, `let [` is an explicit negative lookahead for 4590 // ExpressionStatement, so special-case it first. 4591 if (nextCh === 91 || nextCh === 92) { return true } // '[', '/' 4592 if (context) { return false } 4593 4594 if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral 4595 if (isIdentifierStart(nextCh, true)) { 4596 var pos = next + 1; 4597 while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; } 4598 if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } 4599 var ident = this.input.slice(next, pos); 4600 if (!keywordRelationalOperator.test(ident)) { return true } 4601 } 4602 return false 4603 }; 4604 4605 // check 'async [no LineTerminator here] function' 4606 // - 'async /*foo*/ function' is OK. 4607 // - 'async /*\n*/ function' is invalid. 4608 pp$8.isAsyncFunction = function() { 4609 if (this.options.ecmaVersion < 8 || !this.isContextual("async")) 4610 { return false } 4611 4612 skipWhiteSpace.lastIndex = this.pos; 4613 var skip = skipWhiteSpace.exec(this.input); 4614 var next = this.pos + skip[0].length, after; 4615 return !lineBreak.test(this.input.slice(this.pos, next)) && 4616 this.input.slice(next, next + 8) === "function" && 4617 (next + 8 === this.input.length || 4618 !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00)) 4619 }; 4620 4621 // Parse a single statement. 4622 // 4623 // If expecting a statement and finding a slash operator, parse a 4624 // regular expression literal. This is to handle cases like 4625 // `if (foo) /blah/.exec(foo)`, where looking at the previous token 4626 // does not help. 4627 4628 pp$8.parseStatement = function(context, topLevel, exports) { 4629 var starttype = this.type, node = this.startNode(), kind; 4630 4631 if (this.isLet(context)) { 4632 starttype = types$1._var; 4633 kind = "let"; 4634 } 4635 4636 // Most types of statements are recognized by the keyword they 4637 // start with. Many are trivial to parse, some require a bit of 4638 // complexity. 4639 4640 switch (starttype) { 4641 case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword) 4642 case types$1._debugger: return this.parseDebuggerStatement(node) 4643 case types$1._do: return this.parseDoStatement(node) 4644 case types$1._for: return this.parseForStatement(node) 4645 case types$1._function: 4646 // Function as sole body of either an if statement or a labeled statement 4647 // works, but not when it is part of a labeled statement that is the sole 4648 // body of an if statement. 4649 if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } 4650 return this.parseFunctionStatement(node, false, !context) 4651 case types$1._class: 4652 if (context) { this.unexpected(); } 4653 return this.parseClass(node, true) 4654 case types$1._if: return this.parseIfStatement(node) 4655 case types$1._return: return this.parseReturnStatement(node) 4656 case types$1._switch: return this.parseSwitchStatement(node) 4657 case types$1._throw: return this.parseThrowStatement(node) 4658 case types$1._try: return this.parseTryStatement(node) 4659 case types$1._const: case types$1._var: 4660 kind = kind || this.value; 4661 if (context && kind !== "var") { this.unexpected(); } 4662 return this.parseVarStatement(node, kind) 4663 case types$1._while: return this.parseWhileStatement(node) 4664 case types$1._with: return this.parseWithStatement(node) 4665 case types$1.braceL: return this.parseBlock(true, node) 4666 case types$1.semi: return this.parseEmptyStatement(node) 4667 case types$1._export: 4668 case types$1._import: 4669 if (this.options.ecmaVersion > 10 && starttype === types$1._import) { 4670 skipWhiteSpace.lastIndex = this.pos; 4671 var skip = skipWhiteSpace.exec(this.input); 4672 var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); 4673 if (nextCh === 40 || nextCh === 46) // '(' or '.' 4674 { return this.parseExpressionStatement(node, this.parseExpression()) } 4675 } 4676 4677 if (!this.options.allowImportExportEverywhere) { 4678 if (!topLevel) 4679 { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } 4680 if (!this.inModule) 4681 { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } 4682 } 4683 return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports) 4684 4685 // If the statement does not start with a statement keyword or a 4686 // brace, it's an ExpressionStatement or LabeledStatement. We 4687 // simply start parsing an expression, and afterwards, if the 4688 // next token is a colon and the expression was a simple 4689 // Identifier node, we switch to interpreting it as a label. 4690 default: 4691 if (this.isAsyncFunction()) { 4692 if (context) { this.unexpected(); } 4693 this.next(); 4694 return this.parseFunctionStatement(node, true, !context) 4695 } 4696 4697 var maybeName = this.value, expr = this.parseExpression(); 4698 if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon)) 4699 { return this.parseLabeledStatement(node, maybeName, expr, context) } 4700 else { return this.parseExpressionStatement(node, expr) } 4701 } 4702 }; 4703 4704 pp$8.parseBreakContinueStatement = function(node, keyword) { 4705 var isBreak = keyword === "break"; 4706 this.next(); 4707 if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; } 4708 else if (this.type !== types$1.name) { this.unexpected(); } 4709 else { 4710 node.label = this.parseIdent(); 4711 this.semicolon(); 4712 } 4713 4714 // Verify that there is an actual destination to break or 4715 // continue to. 4716 var i = 0; 4717 for (; i < this.labels.length; ++i) { 4718 var lab = this.labels[i]; 4719 if (node.label == null || lab.name === node.label.name) { 4720 if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } 4721 if (node.label && isBreak) { break } 4722 } 4723 } 4724 if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } 4725 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") 4726 }; 4727 4728 pp$8.parseDebuggerStatement = function(node) { 4729 this.next(); 4730 this.semicolon(); 4731 return this.finishNode(node, "DebuggerStatement") 4732 }; 4733 4734 pp$8.parseDoStatement = function(node) { 4735 this.next(); 4736 this.labels.push(loopLabel); 4737 node.body = this.parseStatement("do"); 4738 this.labels.pop(); 4739 this.expect(types$1._while); 4740 node.test = this.parseParenExpression(); 4741 if (this.options.ecmaVersion >= 6) 4742 { this.eat(types$1.semi); } 4743 else 4744 { this.semicolon(); } 4745 return this.finishNode(node, "DoWhileStatement") 4746 }; 4747 4748 // Disambiguating between a `for` and a `for`/`in` or `for`/`of` 4749 // loop is non-trivial. Basically, we have to parse the init `var` 4750 // statement or expression, disallowing the `in` operator (see 4751 // the second parameter to `parseExpression`), and then check 4752 // whether the next token is `in` or `of`. When there is no init 4753 // part (semicolon immediately after the opening parenthesis), it 4754 // is a regular `for` loop. 4755 4756 pp$8.parseForStatement = function(node) { 4757 this.next(); 4758 var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1; 4759 this.labels.push(loopLabel); 4760 this.enterScope(0); 4761 this.expect(types$1.parenL); 4762 if (this.type === types$1.semi) { 4763 if (awaitAt > -1) { this.unexpected(awaitAt); } 4764 return this.parseFor(node, null) 4765 } 4766 var isLet = this.isLet(); 4767 if (this.type === types$1._var || this.type === types$1._const || isLet) { 4768 var init$1 = this.startNode(), kind = isLet ? "let" : this.value; 4769 this.next(); 4770 this.parseVar(init$1, true, kind); 4771 this.finishNode(init$1, "VariableDeclaration"); 4772 if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) { 4773 if (this.options.ecmaVersion >= 9) { 4774 if (this.type === types$1._in) { 4775 if (awaitAt > -1) { this.unexpected(awaitAt); } 4776 } else { node.await = awaitAt > -1; } 4777 } 4778 return this.parseForIn(node, init$1) 4779 } 4780 if (awaitAt > -1) { this.unexpected(awaitAt); } 4781 return this.parseFor(node, init$1) 4782 } 4783 var startsWithLet = this.isContextual("let"), isForOf = false; 4784 var refDestructuringErrors = new DestructuringErrors; 4785 var init = this.parseExpression(awaitAt > -1 ? "await" : true, refDestructuringErrors); 4786 if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { 4787 if (this.options.ecmaVersion >= 9) { 4788 if (this.type === types$1._in) { 4789 if (awaitAt > -1) { this.unexpected(awaitAt); } 4790 } else { node.await = awaitAt > -1; } 4791 } 4792 if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } 4793 this.toAssignable(init, false, refDestructuringErrors); 4794 this.checkLValPattern(init); 4795 return this.parseForIn(node, init) 4796 } else { 4797 this.checkExpressionErrors(refDestructuringErrors, true); 4798 } 4799 if (awaitAt > -1) { this.unexpected(awaitAt); } 4800 return this.parseFor(node, init) 4801 }; 4802 4803 pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) { 4804 this.next(); 4805 return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) 4806 }; 4807 4808 pp$8.parseIfStatement = function(node) { 4809 this.next(); 4810 node.test = this.parseParenExpression(); 4811 // allow function declarations in branches, but only in non-strict mode 4812 node.consequent = this.parseStatement("if"); 4813 node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null; 4814 return this.finishNode(node, "IfStatement") 4815 }; 4816 4817 pp$8.parseReturnStatement = function(node) { 4818 if (!this.inFunction && !this.options.allowReturnOutsideFunction) 4819 { this.raise(this.start, "'return' outside of function"); } 4820 this.next(); 4821 4822 // In `return` (and `break`/`continue`), the keywords with 4823 // optional arguments, we eagerly look for a semicolon or the 4824 // possibility to insert one. 4825 4826 if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; } 4827 else { node.argument = this.parseExpression(); this.semicolon(); } 4828 return this.finishNode(node, "ReturnStatement") 4829 }; 4830 4831 pp$8.parseSwitchStatement = function(node) { 4832 this.next(); 4833 node.discriminant = this.parseParenExpression(); 4834 node.cases = []; 4835 this.expect(types$1.braceL); 4836 this.labels.push(switchLabel); 4837 this.enterScope(0); 4838 4839 // Statements under must be grouped (by label) in SwitchCase 4840 // nodes. `cur` is used to keep the node that we are currently 4841 // adding statements to. 4842 4843 var cur; 4844 for (var sawDefault = false; this.type !== types$1.braceR;) { 4845 if (this.type === types$1._case || this.type === types$1._default) { 4846 var isCase = this.type === types$1._case; 4847 if (cur) { this.finishNode(cur, "SwitchCase"); } 4848 node.cases.push(cur = this.startNode()); 4849 cur.consequent = []; 4850 this.next(); 4851 if (isCase) { 4852 cur.test = this.parseExpression(); 4853 } else { 4854 if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } 4855 sawDefault = true; 4856 cur.test = null; 4857 } 4858 this.expect(types$1.colon); 4859 } else { 4860 if (!cur) { this.unexpected(); } 4861 cur.consequent.push(this.parseStatement(null)); 4862 } 4863 } 4864 this.exitScope(); 4865 if (cur) { this.finishNode(cur, "SwitchCase"); } 4866 this.next(); // Closing brace 4867 this.labels.pop(); 4868 return this.finishNode(node, "SwitchStatement") 4869 }; 4870 4871 pp$8.parseThrowStatement = function(node) { 4872 this.next(); 4873 if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) 4874 { this.raise(this.lastTokEnd, "Illegal newline after throw"); } 4875 node.argument = this.parseExpression(); 4876 this.semicolon(); 4877 return this.finishNode(node, "ThrowStatement") 4878 }; 4879 4880 // Reused empty array added for node fields that are always empty. 4881 4882 var empty$1 = []; 4883 4884 pp$8.parseTryStatement = function(node) { 4885 this.next(); 4886 node.block = this.parseBlock(); 4887 node.handler = null; 4888 if (this.type === types$1._catch) { 4889 var clause = this.startNode(); 4890 this.next(); 4891 if (this.eat(types$1.parenL)) { 4892 clause.param = this.parseBindingAtom(); 4893 var simple = clause.param.type === "Identifier"; 4894 this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); 4895 this.checkLValPattern(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); 4896 this.expect(types$1.parenR); 4897 } else { 4898 if (this.options.ecmaVersion < 10) { this.unexpected(); } 4899 clause.param = null; 4900 this.enterScope(0); 4901 } 4902 clause.body = this.parseBlock(false); 4903 this.exitScope(); 4904 node.handler = this.finishNode(clause, "CatchClause"); 4905 } 4906 node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null; 4907 if (!node.handler && !node.finalizer) 4908 { this.raise(node.start, "Missing catch or finally clause"); } 4909 return this.finishNode(node, "TryStatement") 4910 }; 4911 4912 pp$8.parseVarStatement = function(node, kind) { 4913 this.next(); 4914 this.parseVar(node, false, kind); 4915 this.semicolon(); 4916 return this.finishNode(node, "VariableDeclaration") 4917 }; 4918 4919 pp$8.parseWhileStatement = function(node) { 4920 this.next(); 4921 node.test = this.parseParenExpression(); 4922 this.labels.push(loopLabel); 4923 node.body = this.parseStatement("while"); 4924 this.labels.pop(); 4925 return this.finishNode(node, "WhileStatement") 4926 }; 4927 4928 pp$8.parseWithStatement = function(node) { 4929 if (this.strict) { this.raise(this.start, "'with' in strict mode"); } 4930 this.next(); 4931 node.object = this.parseParenExpression(); 4932 node.body = this.parseStatement("with"); 4933 return this.finishNode(node, "WithStatement") 4934 }; 4935 4936 pp$8.parseEmptyStatement = function(node) { 4937 this.next(); 4938 return this.finishNode(node, "EmptyStatement") 4939 }; 4940 4941 pp$8.parseLabeledStatement = function(node, maybeName, expr, context) { 4942 for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) 4943 { 4944 var label = list[i$1]; 4945 4946 if (label.name === maybeName) 4947 { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); 4948 } } 4949 var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null; 4950 for (var i = this.labels.length - 1; i >= 0; i--) { 4951 var label$1 = this.labels[i]; 4952 if (label$1.statementStart === node.start) { 4953 // Update information about previous labels on this node 4954 label$1.statementStart = this.start; 4955 label$1.kind = kind; 4956 } else { break } 4957 } 4958 this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); 4959 node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); 4960 this.labels.pop(); 4961 node.label = expr; 4962 return this.finishNode(node, "LabeledStatement") 4963 }; 4964 4965 pp$8.parseExpressionStatement = function(node, expr) { 4966 node.expression = expr; 4967 this.semicolon(); 4968 return this.finishNode(node, "ExpressionStatement") 4969 }; 4970 4971 // Parse a semicolon-enclosed block of statements, handling `"use 4972 // strict"` declarations when `allowStrict` is true (used for 4973 // function bodies). 4974 4975 pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) { 4976 if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; 4977 if ( node === void 0 ) node = this.startNode(); 4978 4979 node.body = []; 4980 this.expect(types$1.braceL); 4981 if (createNewLexicalScope) { this.enterScope(0); } 4982 while (this.type !== types$1.braceR) { 4983 var stmt = this.parseStatement(null); 4984 node.body.push(stmt); 4985 } 4986 if (exitStrict) { this.strict = false; } 4987 this.next(); 4988 if (createNewLexicalScope) { this.exitScope(); } 4989 return this.finishNode(node, "BlockStatement") 4990 }; 4991 4992 // Parse a regular `for` loop. The disambiguation code in 4993 // `parseStatement` will already have parsed the init statement or 4994 // expression. 4995 4996 pp$8.parseFor = function(node, init) { 4997 node.init = init; 4998 this.expect(types$1.semi); 4999 node.test = this.type === types$1.semi ? null : this.parseExpression(); 5000 this.expect(types$1.semi); 5001 node.update = this.type === types$1.parenR ? null : this.parseExpression(); 5002 this.expect(types$1.parenR); 5003 node.body = this.parseStatement("for"); 5004 this.exitScope(); 5005 this.labels.pop(); 5006 return this.finishNode(node, "ForStatement") 5007 }; 5008 5009 // Parse a `for`/`in` and `for`/`of` loop, which are almost 5010 // same from parser's perspective. 5011 5012 pp$8.parseForIn = function(node, init) { 5013 var isForIn = this.type === types$1._in; 5014 this.next(); 5015 5016 if ( 5017 init.type === "VariableDeclaration" && 5018 init.declarations[0].init != null && 5019 ( 5020 !isForIn || 5021 this.options.ecmaVersion < 8 || 5022 this.strict || 5023 init.kind !== "var" || 5024 init.declarations[0].id.type !== "Identifier" 5025 ) 5026 ) { 5027 this.raise( 5028 init.start, 5029 ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") 5030 ); 5031 } 5032 node.left = init; 5033 node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); 5034 this.expect(types$1.parenR); 5035 node.body = this.parseStatement("for"); 5036 this.exitScope(); 5037 this.labels.pop(); 5038 return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") 5039 }; 5040 5041 // Parse a list of variable declarations. 5042 5043 pp$8.parseVar = function(node, isFor, kind) { 5044 node.declarations = []; 5045 node.kind = kind; 5046 for (;;) { 5047 var decl = this.startNode(); 5048 this.parseVarId(decl, kind); 5049 if (this.eat(types$1.eq)) { 5050 decl.init = this.parseMaybeAssign(isFor); 5051 } else if (kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { 5052 this.unexpected(); 5053 } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) { 5054 this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); 5055 } else { 5056 decl.init = null; 5057 } 5058 node.declarations.push(this.finishNode(decl, "VariableDeclarator")); 5059 if (!this.eat(types$1.comma)) { break } 5060 } 5061 return node 5062 }; 5063 5064 pp$8.parseVarId = function(decl, kind) { 5065 decl.id = this.parseBindingAtom(); 5066 this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); 5067 }; 5068 5069 var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; 5070 5071 // Parse a function declaration or literal (depending on the 5072 // `statement & FUNC_STATEMENT`). 5073 5074 // Remove `allowExpressionBody` for 7.0.0, as it is only called with false 5075 pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) { 5076 this.initFunction(node); 5077 if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { 5078 if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT)) 5079 { this.unexpected(); } 5080 node.generator = this.eat(types$1.star); 5081 } 5082 if (this.options.ecmaVersion >= 8) 5083 { node.async = !!isAsync; } 5084 5085 if (statement & FUNC_STATEMENT) { 5086 node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent(); 5087 if (node.id && !(statement & FUNC_HANGING_STATEMENT)) 5088 // If it is a regular function declaration in sloppy mode, then it is 5089 // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding 5090 // mode depends on properties of the current scope (see 5091 // treatFunctionsAsVar). 5092 { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } 5093 } 5094 5095 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; 5096 this.yieldPos = 0; 5097 this.awaitPos = 0; 5098 this.awaitIdentPos = 0; 5099 this.enterScope(functionFlags(node.async, node.generator)); 5100 5101 if (!(statement & FUNC_STATEMENT)) 5102 { node.id = this.type === types$1.name ? this.parseIdent() : null; } 5103 5104 this.parseFunctionParams(node); 5105 this.parseFunctionBody(node, allowExpressionBody, false, forInit); 5106 5107 this.yieldPos = oldYieldPos; 5108 this.awaitPos = oldAwaitPos; 5109 this.awaitIdentPos = oldAwaitIdentPos; 5110 return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") 5111 }; 5112 5113 pp$8.parseFunctionParams = function(node) { 5114 this.expect(types$1.parenL); 5115 node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); 5116 this.checkYieldAwaitInDefaultParams(); 5117 }; 5118 5119 // Parse a class declaration or literal (depending on the 5120 // `isStatement` parameter). 5121 5122 pp$8.parseClass = function(node, isStatement) { 5123 this.next(); 5124 5125 // ecma-262 14.6 Class Definitions 5126 // A class definition is always strict mode code. 5127 var oldStrict = this.strict; 5128 this.strict = true; 5129 5130 this.parseClassId(node, isStatement); 5131 this.parseClassSuper(node); 5132 var privateNameMap = this.enterClassBody(); 5133 var classBody = this.startNode(); 5134 var hadConstructor = false; 5135 classBody.body = []; 5136 this.expect(types$1.braceL); 5137 while (this.type !== types$1.braceR) { 5138 var element = this.parseClassElement(node.superClass !== null); 5139 if (element) { 5140 classBody.body.push(element); 5141 if (element.type === "MethodDefinition" && element.kind === "constructor") { 5142 if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); } 5143 hadConstructor = true; 5144 } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) { 5145 this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared")); 5146 } 5147 } 5148 } 5149 this.strict = oldStrict; 5150 this.next(); 5151 node.body = this.finishNode(classBody, "ClassBody"); 5152 this.exitClassBody(); 5153 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") 5154 }; 5155 5156 pp$8.parseClassElement = function(constructorAllowsSuper) { 5157 if (this.eat(types$1.semi)) { return null } 5158 5159 var ecmaVersion = this.options.ecmaVersion; 5160 var node = this.startNode(); 5161 var keyName = ""; 5162 var isGenerator = false; 5163 var isAsync = false; 5164 var kind = "method"; 5165 var isStatic = false; 5166 5167 if (this.eatContextual("static")) { 5168 // Parse static init block 5169 if (ecmaVersion >= 13 && this.eat(types$1.braceL)) { 5170 this.parseClassStaticBlock(node); 5171 return node 5172 } 5173 if (this.isClassElementNameStart() || this.type === types$1.star) { 5174 isStatic = true; 5175 } else { 5176 keyName = "static"; 5177 } 5178 } 5179 node.static = isStatic; 5180 if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { 5181 if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) { 5182 isAsync = true; 5183 } else { 5184 keyName = "async"; 5185 } 5186 } 5187 if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) { 5188 isGenerator = true; 5189 } 5190 if (!keyName && !isAsync && !isGenerator) { 5191 var lastValue = this.value; 5192 if (this.eatContextual("get") || this.eatContextual("set")) { 5193 if (this.isClassElementNameStart()) { 5194 kind = lastValue; 5195 } else { 5196 keyName = lastValue; 5197 } 5198 } 5199 } 5200 5201 // Parse element name 5202 if (keyName) { 5203 // 'async', 'get', 'set', or 'static' were not a keyword contextually. 5204 // The last token is any of those. Make it the element name. 5205 node.computed = false; 5206 node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); 5207 node.key.name = keyName; 5208 this.finishNode(node.key, "Identifier"); 5209 } else { 5210 this.parseClassElementName(node); 5211 } 5212 5213 // Parse element value 5214 if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) { 5215 var isConstructor = !node.static && checkKeyName(node, "constructor"); 5216 var allowsDirectSuper = isConstructor && constructorAllowsSuper; 5217 // Couldn't move this check into the 'parseClassMethod' method for backward compatibility. 5218 if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); } 5219 node.kind = isConstructor ? "constructor" : kind; 5220 this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper); 5221 } else { 5222 this.parseClassField(node); 5223 } 5224 5225 return node 5226 }; 5227 5228 pp$8.isClassElementNameStart = function() { 5229 return ( 5230 this.type === types$1.name || 5231 this.type === types$1.privateId || 5232 this.type === types$1.num || 5233 this.type === types$1.string || 5234 this.type === types$1.bracketL || 5235 this.type.keyword 5236 ) 5237 }; 5238 5239 pp$8.parseClassElementName = function(element) { 5240 if (this.type === types$1.privateId) { 5241 if (this.value === "constructor") { 5242 this.raise(this.start, "Classes can't have an element named '#constructor'"); 5243 } 5244 element.computed = false; 5245 element.key = this.parsePrivateIdent(); 5246 } else { 5247 this.parsePropertyName(element); 5248 } 5249 }; 5250 5251 pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { 5252 // Check key and flags 5253 var key = method.key; 5254 if (method.kind === "constructor") { 5255 if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } 5256 if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } 5257 } else if (method.static && checkKeyName(method, "prototype")) { 5258 this.raise(key.start, "Classes may not have a static property named prototype"); 5259 } 5260 5261 // Parse value 5262 var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); 5263 5264 // Check value 5265 if (method.kind === "get" && value.params.length !== 0) 5266 { this.raiseRecoverable(value.start, "getter should have no params"); } 5267 if (method.kind === "set" && value.params.length !== 1) 5268 { this.raiseRecoverable(value.start, "setter should have exactly one param"); } 5269 if (method.kind === "set" && value.params[0].type === "RestElement") 5270 { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); } 5271 5272 return this.finishNode(method, "MethodDefinition") 5273 }; 5274 5275 pp$8.parseClassField = function(field) { 5276 if (checkKeyName(field, "constructor")) { 5277 this.raise(field.key.start, "Classes can't have a field named 'constructor'"); 5278 } else if (field.static && checkKeyName(field, "prototype")) { 5279 this.raise(field.key.start, "Classes can't have a static field named 'prototype'"); 5280 } 5281 5282 if (this.eat(types$1.eq)) { 5283 // To raise SyntaxError if 'arguments' exists in the initializer. 5284 var scope = this.currentThisScope(); 5285 var inClassFieldInit = scope.inClassFieldInit; 5286 scope.inClassFieldInit = true; 5287 field.value = this.parseMaybeAssign(); 5288 scope.inClassFieldInit = inClassFieldInit; 5289 } else { 5290 field.value = null; 5291 } 5292 this.semicolon(); 5293 5294 return this.finishNode(field, "PropertyDefinition") 5295 }; 5296 5297 pp$8.parseClassStaticBlock = function(node) { 5298 node.body = []; 5299 5300 var oldLabels = this.labels; 5301 this.labels = []; 5302 this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER); 5303 while (this.type !== types$1.braceR) { 5304 var stmt = this.parseStatement(null); 5305 node.body.push(stmt); 5306 } 5307 this.next(); 5308 this.exitScope(); 5309 this.labels = oldLabels; 5310 5311 return this.finishNode(node, "StaticBlock") 5312 }; 5313 5314 pp$8.parseClassId = function(node, isStatement) { 5315 if (this.type === types$1.name) { 5316 node.id = this.parseIdent(); 5317 if (isStatement) 5318 { this.checkLValSimple(node.id, BIND_LEXICAL, false); } 5319 } else { 5320 if (isStatement === true) 5321 { this.unexpected(); } 5322 node.id = null; 5323 } 5324 }; 5325 5326 pp$8.parseClassSuper = function(node) { 5327 node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null; 5328 }; 5329 5330 pp$8.enterClassBody = function() { 5331 var element = {declared: Object.create(null), used: []}; 5332 this.privateNameStack.push(element); 5333 return element.declared 5334 }; 5335 5336 pp$8.exitClassBody = function() { 5337 var ref = this.privateNameStack.pop(); 5338 var declared = ref.declared; 5339 var used = ref.used; 5340 var len = this.privateNameStack.length; 5341 var parent = len === 0 ? null : this.privateNameStack[len - 1]; 5342 for (var i = 0; i < used.length; ++i) { 5343 var id = used[i]; 5344 if (!hasOwn(declared, id.name)) { 5345 if (parent) { 5346 parent.used.push(id); 5347 } else { 5348 this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class")); 5349 } 5350 } 5351 } 5352 }; 5353 5354 function isPrivateNameConflicted(privateNameMap, element) { 5355 var name = element.key.name; 5356 var curr = privateNameMap[name]; 5357 5358 var next = "true"; 5359 if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) { 5360 next = (element.static ? "s" : "i") + element.kind; 5361 } 5362 5363 // `class { get #a(){}; static set #a(_){} }` is also conflict. 5364 if ( 5365 curr === "iget" && next === "iset" || 5366 curr === "iset" && next === "iget" || 5367 curr === "sget" && next === "sset" || 5368 curr === "sset" && next === "sget" 5369 ) { 5370 privateNameMap[name] = "true"; 5371 return false 5372 } else if (!curr) { 5373 privateNameMap[name] = next; 5374 return false 5375 } else { 5376 return true 5377 } 5378 } 5379 5380 function checkKeyName(node, name) { 5381 var computed = node.computed; 5382 var key = node.key; 5383 return !computed && ( 5384 key.type === "Identifier" && key.name === name || 5385 key.type === "Literal" && key.value === name 5386 ) 5387 } 5388 5389 // Parses module export declaration. 5390 5391 pp$8.parseExport = function(node, exports) { 5392 this.next(); 5393 // export * from '...' 5394 if (this.eat(types$1.star)) { 5395 if (this.options.ecmaVersion >= 11) { 5396 if (this.eatContextual("as")) { 5397 node.exported = this.parseModuleExportName(); 5398 this.checkExport(exports, node.exported, this.lastTokStart); 5399 } else { 5400 node.exported = null; 5401 } 5402 } 5403 this.expectContextual("from"); 5404 if (this.type !== types$1.string) { this.unexpected(); } 5405 node.source = this.parseExprAtom(); 5406 this.semicolon(); 5407 return this.finishNode(node, "ExportAllDeclaration") 5408 } 5409 if (this.eat(types$1._default)) { // export default ... 5410 this.checkExport(exports, "default", this.lastTokStart); 5411 var isAsync; 5412 if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) { 5413 var fNode = this.startNode(); 5414 this.next(); 5415 if (isAsync) { this.next(); } 5416 node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); 5417 } else if (this.type === types$1._class) { 5418 var cNode = this.startNode(); 5419 node.declaration = this.parseClass(cNode, "nullableID"); 5420 } else { 5421 node.declaration = this.parseMaybeAssign(); 5422 this.semicolon(); 5423 } 5424 return this.finishNode(node, "ExportDefaultDeclaration") 5425 } 5426 // export var|const|let|function|class ... 5427 if (this.shouldParseExportStatement()) { 5428 node.declaration = this.parseStatement(null); 5429 if (node.declaration.type === "VariableDeclaration") 5430 { this.checkVariableExport(exports, node.declaration.declarations); } 5431 else 5432 { this.checkExport(exports, node.declaration.id, node.declaration.id.start); } 5433 node.specifiers = []; 5434 node.source = null; 5435 } else { // export { x, y as z } [from '...'] 5436 node.declaration = null; 5437 node.specifiers = this.parseExportSpecifiers(exports); 5438 if (this.eatContextual("from")) { 5439 if (this.type !== types$1.string) { this.unexpected(); } 5440 node.source = this.parseExprAtom(); 5441 } else { 5442 for (var i = 0, list = node.specifiers; i < list.length; i += 1) { 5443 // check for keywords used as local names 5444 var spec = list[i]; 5445 5446 this.checkUnreserved(spec.local); 5447 // check if export is defined 5448 this.checkLocalExport(spec.local); 5449 5450 if (spec.local.type === "Literal") { 5451 this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`."); 5452 } 5453 } 5454 5455 node.source = null; 5456 } 5457 this.semicolon(); 5458 } 5459 return this.finishNode(node, "ExportNamedDeclaration") 5460 }; 5461 5462 pp$8.checkExport = function(exports, name, pos) { 5463 if (!exports) { return } 5464 if (typeof name !== "string") 5465 { name = name.type === "Identifier" ? name.name : name.value; } 5466 if (hasOwn(exports, name)) 5467 { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } 5468 exports[name] = true; 5469 }; 5470 5471 pp$8.checkPatternExport = function(exports, pat) { 5472 var type = pat.type; 5473 if (type === "Identifier") 5474 { this.checkExport(exports, pat, pat.start); } 5475 else if (type === "ObjectPattern") 5476 { for (var i = 0, list = pat.properties; i < list.length; i += 1) 5477 { 5478 var prop = list[i]; 5479 5480 this.checkPatternExport(exports, prop); 5481 } } 5482 else if (type === "ArrayPattern") 5483 { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { 5484 var elt = list$1[i$1]; 5485 5486 if (elt) { this.checkPatternExport(exports, elt); } 5487 } } 5488 else if (type === "Property") 5489 { this.checkPatternExport(exports, pat.value); } 5490 else if (type === "AssignmentPattern") 5491 { this.checkPatternExport(exports, pat.left); } 5492 else if (type === "RestElement") 5493 { this.checkPatternExport(exports, pat.argument); } 5494 else if (type === "ParenthesizedExpression") 5495 { this.checkPatternExport(exports, pat.expression); } 5496 }; 5497 5498 pp$8.checkVariableExport = function(exports, decls) { 5499 if (!exports) { return } 5500 for (var i = 0, list = decls; i < list.length; i += 1) 5501 { 5502 var decl = list[i]; 5503 5504 this.checkPatternExport(exports, decl.id); 5505 } 5506 }; 5507 5508 pp$8.shouldParseExportStatement = function() { 5509 return this.type.keyword === "var" || 5510 this.type.keyword === "const" || 5511 this.type.keyword === "class" || 5512 this.type.keyword === "function" || 5513 this.isLet() || 5514 this.isAsyncFunction() 5515 }; 5516 5517 // Parses a comma-separated list of module exports. 5518 5519 pp$8.parseExportSpecifiers = function(exports) { 5520 var nodes = [], first = true; 5521 // export { x, y as z } [from '...'] 5522 this.expect(types$1.braceL); 5523 while (!this.eat(types$1.braceR)) { 5524 if (!first) { 5525 this.expect(types$1.comma); 5526 if (this.afterTrailingComma(types$1.braceR)) { break } 5527 } else { first = false; } 5528 5529 var node = this.startNode(); 5530 node.local = this.parseModuleExportName(); 5531 node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local; 5532 this.checkExport( 5533 exports, 5534 node.exported, 5535 node.exported.start 5536 ); 5537 nodes.push(this.finishNode(node, "ExportSpecifier")); 5538 } 5539 return nodes 5540 }; 5541 5542 // Parses import declaration. 5543 5544 pp$8.parseImport = function(node) { 5545 this.next(); 5546 // import '...' 5547 if (this.type === types$1.string) { 5548 node.specifiers = empty$1; 5549 node.source = this.parseExprAtom(); 5550 } else { 5551 node.specifiers = this.parseImportSpecifiers(); 5552 this.expectContextual("from"); 5553 node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected(); 5554 } 5555 this.semicolon(); 5556 return this.finishNode(node, "ImportDeclaration") 5557 }; 5558 5559 // Parses a comma-separated list of module imports. 5560 5561 pp$8.parseImportSpecifiers = function() { 5562 var nodes = [], first = true; 5563 if (this.type === types$1.name) { 5564 // import defaultObj, { x, y as z } from '...' 5565 var node = this.startNode(); 5566 node.local = this.parseIdent(); 5567 this.checkLValSimple(node.local, BIND_LEXICAL); 5568 nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); 5569 if (!this.eat(types$1.comma)) { return nodes } 5570 } 5571 if (this.type === types$1.star) { 5572 var node$1 = this.startNode(); 5573 this.next(); 5574 this.expectContextual("as"); 5575 node$1.local = this.parseIdent(); 5576 this.checkLValSimple(node$1.local, BIND_LEXICAL); 5577 nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); 5578 return nodes 5579 } 5580 this.expect(types$1.braceL); 5581 while (!this.eat(types$1.braceR)) { 5582 if (!first) { 5583 this.expect(types$1.comma); 5584 if (this.afterTrailingComma(types$1.braceR)) { break } 5585 } else { first = false; } 5586 5587 var node$2 = this.startNode(); 5588 node$2.imported = this.parseModuleExportName(); 5589 if (this.eatContextual("as")) { 5590 node$2.local = this.parseIdent(); 5591 } else { 5592 this.checkUnreserved(node$2.imported); 5593 node$2.local = node$2.imported; 5594 } 5595 this.checkLValSimple(node$2.local, BIND_LEXICAL); 5596 nodes.push(this.finishNode(node$2, "ImportSpecifier")); 5597 } 5598 return nodes 5599 }; 5600 5601 pp$8.parseModuleExportName = function() { 5602 if (this.options.ecmaVersion >= 13 && this.type === types$1.string) { 5603 var stringLiteral = this.parseLiteral(this.value); 5604 if (loneSurrogate.test(stringLiteral.value)) { 5605 this.raise(stringLiteral.start, "An export name cannot include a lone surrogate."); 5606 } 5607 return stringLiteral 5608 } 5609 return this.parseIdent(true) 5610 }; 5611 5612 // Set `ExpressionStatement#directive` property for directive prologues. 5613 pp$8.adaptDirectivePrologue = function(statements) { 5614 for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { 5615 statements[i].directive = statements[i].expression.raw.slice(1, -1); 5616 } 5617 }; 5618 pp$8.isDirectiveCandidate = function(statement) { 5619 return ( 5620 this.options.ecmaVersion >= 5 && 5621 statement.type === "ExpressionStatement" && 5622 statement.expression.type === "Literal" && 5623 typeof statement.expression.value === "string" && 5624 // Reject parenthesized strings. 5625 (this.input[statement.start] === "\"" || this.input[statement.start] === "'") 5626 ) 5627 }; 5628 5629 var pp$7 = Parser.prototype; 5630 5631 // Convert existing expression atom to assignable pattern 5632 // if possible. 5633 5634 pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) { 5635 if (this.options.ecmaVersion >= 6 && node) { 5636 switch (node.type) { 5637 case "Identifier": 5638 if (this.inAsync && node.name === "await") 5639 { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } 5640 break 5641 5642 case "ObjectPattern": 5643 case "ArrayPattern": 5644 case "AssignmentPattern": 5645 case "RestElement": 5646 break 5647 5648 case "ObjectExpression": 5649 node.type = "ObjectPattern"; 5650 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } 5651 for (var i = 0, list = node.properties; i < list.length; i += 1) { 5652 var prop = list[i]; 5653 5654 this.toAssignable(prop, isBinding); 5655 // Early error: 5656 // AssignmentRestProperty[Yield, Await] : 5657 // `...` DestructuringAssignmentTarget[Yield, Await] 5658 // 5659 // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. 5660 if ( 5661 prop.type === "RestElement" && 5662 (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") 5663 ) { 5664 this.raise(prop.argument.start, "Unexpected token"); 5665 } 5666 } 5667 break 5668 5669 case "Property": 5670 // AssignmentProperty has type === "Property" 5671 if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } 5672 this.toAssignable(node.value, isBinding); 5673 break 5674 5675 case "ArrayExpression": 5676 node.type = "ArrayPattern"; 5677 if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } 5678 this.toAssignableList(node.elements, isBinding); 5679 break 5680 5681 case "SpreadElement": 5682 node.type = "RestElement"; 5683 this.toAssignable(node.argument, isBinding); 5684 if (node.argument.type === "AssignmentPattern") 5685 { this.raise(node.argument.start, "Rest elements cannot have a default value"); } 5686 break 5687 5688 case "AssignmentExpression": 5689 if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } 5690 node.type = "AssignmentPattern"; 5691 delete node.operator; 5692 this.toAssignable(node.left, isBinding); 5693 break 5694 5695 case "ParenthesizedExpression": 5696 this.toAssignable(node.expression, isBinding, refDestructuringErrors); 5697 break 5698 5699 case "ChainExpression": 5700 this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); 5701 break 5702 5703 case "MemberExpression": 5704 if (!isBinding) { break } 5705 5706 default: 5707 this.raise(node.start, "Assigning to rvalue"); 5708 } 5709 } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } 5710 return node 5711 }; 5712 5713 // Convert list of expression atoms to binding list. 5714 5715 pp$7.toAssignableList = function(exprList, isBinding) { 5716 var end = exprList.length; 5717 for (var i = 0; i < end; i++) { 5718 var elt = exprList[i]; 5719 if (elt) { this.toAssignable(elt, isBinding); } 5720 } 5721 if (end) { 5722 var last = exprList[end - 1]; 5723 if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") 5724 { this.unexpected(last.argument.start); } 5725 } 5726 return exprList 5727 }; 5728 5729 // Parses spread element. 5730 5731 pp$7.parseSpread = function(refDestructuringErrors) { 5732 var node = this.startNode(); 5733 this.next(); 5734 node.argument = this.parseMaybeAssign(false, refDestructuringErrors); 5735 return this.finishNode(node, "SpreadElement") 5736 }; 5737 5738 pp$7.parseRestBinding = function() { 5739 var node = this.startNode(); 5740 this.next(); 5741 5742 // RestElement inside of a function parameter must be an identifier 5743 if (this.options.ecmaVersion === 6 && this.type !== types$1.name) 5744 { this.unexpected(); } 5745 5746 node.argument = this.parseBindingAtom(); 5747 5748 return this.finishNode(node, "RestElement") 5749 }; 5750 5751 // Parses lvalue (assignable) atom. 5752 5753 pp$7.parseBindingAtom = function() { 5754 if (this.options.ecmaVersion >= 6) { 5755 switch (this.type) { 5756 case types$1.bracketL: 5757 var node = this.startNode(); 5758 this.next(); 5759 node.elements = this.parseBindingList(types$1.bracketR, true, true); 5760 return this.finishNode(node, "ArrayPattern") 5761 5762 case types$1.braceL: 5763 return this.parseObj(true) 5764 } 5765 } 5766 return this.parseIdent() 5767 }; 5768 5769 pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma) { 5770 var elts = [], first = true; 5771 while (!this.eat(close)) { 5772 if (first) { first = false; } 5773 else { this.expect(types$1.comma); } 5774 if (allowEmpty && this.type === types$1.comma) { 5775 elts.push(null); 5776 } else if (allowTrailingComma && this.afterTrailingComma(close)) { 5777 break 5778 } else if (this.type === types$1.ellipsis) { 5779 var rest = this.parseRestBinding(); 5780 this.parseBindingListItem(rest); 5781 elts.push(rest); 5782 if (this.type === types$1.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } 5783 this.expect(close); 5784 break 5785 } else { 5786 var elem = this.parseMaybeDefault(this.start, this.startLoc); 5787 this.parseBindingListItem(elem); 5788 elts.push(elem); 5789 } 5790 } 5791 return elts 5792 }; 5793 5794 pp$7.parseBindingListItem = function(param) { 5795 return param 5796 }; 5797 5798 // Parses assignment pattern around given atom if possible. 5799 5800 pp$7.parseMaybeDefault = function(startPos, startLoc, left) { 5801 left = left || this.parseBindingAtom(); 5802 if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left } 5803 var node = this.startNodeAt(startPos, startLoc); 5804 node.left = left; 5805 node.right = this.parseMaybeAssign(); 5806 return this.finishNode(node, "AssignmentPattern") 5807 }; 5808 5809 // The following three functions all verify that a node is an lvalue — 5810 // something that can be bound, or assigned to. In order to do so, they perform 5811 // a variety of checks: 5812 // 5813 // - Check that none of the bound/assigned-to identifiers are reserved words. 5814 // - Record name declarations for bindings in the appropriate scope. 5815 // - Check duplicate argument names, if checkClashes is set. 5816 // 5817 // If a complex binding pattern is encountered (e.g., object and array 5818 // destructuring), the entire pattern is recursively checked. 5819 // 5820 // There are three versions of checkLVal*() appropriate for different 5821 // circumstances: 5822 // 5823 // - checkLValSimple() shall be used if the syntactic construct supports 5824 // nothing other than identifiers and member expressions. Parenthesized 5825 // expressions are also correctly handled. This is generally appropriate for 5826 // constructs for which the spec says 5827 // 5828 // > It is a Syntax Error if AssignmentTargetType of [the production] is not 5829 // > simple. 5830 // 5831 // It is also appropriate for checking if an identifier is valid and not 5832 // defined elsewhere, like import declarations or function/class identifiers. 5833 // 5834 // Examples where this is used include: 5835 // a += …; 5836 // import a from '…'; 5837 // where a is the node to be checked. 5838 // 5839 // - checkLValPattern() shall be used if the syntactic construct supports 5840 // anything checkLValSimple() supports, as well as object and array 5841 // destructuring patterns. This is generally appropriate for constructs for 5842 // which the spec says 5843 // 5844 // > It is a Syntax Error if [the production] is neither an ObjectLiteral nor 5845 // > an ArrayLiteral and AssignmentTargetType of [the production] is not 5846 // > simple. 5847 // 5848 // Examples where this is used include: 5849 // (a = …); 5850 // const a = …; 5851 // try { … } catch (a) { … } 5852 // where a is the node to be checked. 5853 // 5854 // - checkLValInnerPattern() shall be used if the syntactic construct supports 5855 // anything checkLValPattern() supports, as well as default assignment 5856 // patterns, rest elements, and other constructs that may appear within an 5857 // object or array destructuring pattern. 5858 // 5859 // As a special case, function parameters also use checkLValInnerPattern(), 5860 // as they also support defaults and rest constructs. 5861 // 5862 // These functions deliberately support both assignment and binding constructs, 5863 // as the logic for both is exceedingly similar. If the node is the target of 5864 // an assignment, then bindingType should be set to BIND_NONE. Otherwise, it 5865 // should be set to the appropriate BIND_* constant, like BIND_VAR or 5866 // BIND_LEXICAL. 5867 // 5868 // If the function is called with a non-BIND_NONE bindingType, then 5869 // additionally a checkClashes object may be specified to allow checking for 5870 // duplicate argument names. checkClashes is ignored if the provided construct 5871 // is an assignment (i.e., bindingType is BIND_NONE). 5872 5873 pp$7.checkLValSimple = function(expr, bindingType, checkClashes) { 5874 if ( bindingType === void 0 ) bindingType = BIND_NONE; 5875 5876 var isBind = bindingType !== BIND_NONE; 5877 5878 switch (expr.type) { 5879 case "Identifier": 5880 if (this.strict && this.reservedWordsStrictBind.test(expr.name)) 5881 { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } 5882 if (isBind) { 5883 if (bindingType === BIND_LEXICAL && expr.name === "let") 5884 { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } 5885 if (checkClashes) { 5886 if (hasOwn(checkClashes, expr.name)) 5887 { this.raiseRecoverable(expr.start, "Argument name clash"); } 5888 checkClashes[expr.name] = true; 5889 } 5890 if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } 5891 } 5892 break 5893 5894 case "ChainExpression": 5895 this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); 5896 break 5897 5898 case "MemberExpression": 5899 if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); } 5900 break 5901 5902 case "ParenthesizedExpression": 5903 if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); } 5904 return this.checkLValSimple(expr.expression, bindingType, checkClashes) 5905 5906 default: 5907 this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue"); 5908 } 5909 }; 5910 5911 pp$7.checkLValPattern = function(expr, bindingType, checkClashes) { 5912 if ( bindingType === void 0 ) bindingType = BIND_NONE; 5913 5914 switch (expr.type) { 5915 case "ObjectPattern": 5916 for (var i = 0, list = expr.properties; i < list.length; i += 1) { 5917 var prop = list[i]; 5918 5919 this.checkLValInnerPattern(prop, bindingType, checkClashes); 5920 } 5921 break 5922 5923 case "ArrayPattern": 5924 for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { 5925 var elem = list$1[i$1]; 5926 5927 if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); } 5928 } 5929 break 5930 5931 default: 5932 this.checkLValSimple(expr, bindingType, checkClashes); 5933 } 5934 }; 5935 5936 pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) { 5937 if ( bindingType === void 0 ) bindingType = BIND_NONE; 5938 5939 switch (expr.type) { 5940 case "Property": 5941 // AssignmentProperty has type === "Property" 5942 this.checkLValInnerPattern(expr.value, bindingType, checkClashes); 5943 break 5944 5945 case "AssignmentPattern": 5946 this.checkLValPattern(expr.left, bindingType, checkClashes); 5947 break 5948 5949 case "RestElement": 5950 this.checkLValPattern(expr.argument, bindingType, checkClashes); 5951 break 5952 5953 default: 5954 this.checkLValPattern(expr, bindingType, checkClashes); 5955 } 5956 }; 5957 5958 // The algorithm used to determine whether a regexp can appear at a 5959 5960 var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { 5961 this.token = token; 5962 this.isExpr = !!isExpr; 5963 this.preserveSpace = !!preserveSpace; 5964 this.override = override; 5965 this.generator = !!generator; 5966 }; 5967 5968 var types = { 5969 b_stat: new TokContext("{", false), 5970 b_expr: new TokContext("{", true), 5971 b_tmpl: new TokContext("${", false), 5972 p_stat: new TokContext("(", false), 5973 p_expr: new TokContext("(", true), 5974 q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), 5975 f_stat: new TokContext("function", false), 5976 f_expr: new TokContext("function", true), 5977 f_expr_gen: new TokContext("function", true, false, null, true), 5978 f_gen: new TokContext("function", false, false, null, true) 5979 }; 5980 5981 var pp$6 = Parser.prototype; 5982 5983 pp$6.initialContext = function() { 5984 return [types.b_stat] 5985 }; 5986 5987 pp$6.curContext = function() { 5988 return this.context[this.context.length - 1] 5989 }; 5990 5991 pp$6.braceIsBlock = function(prevType) { 5992 var parent = this.curContext(); 5993 if (parent === types.f_expr || parent === types.f_stat) 5994 { return true } 5995 if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr)) 5996 { return !parent.isExpr } 5997 5998 // The check for `tt.name && exprAllowed` detects whether we are 5999 // after a `yield` or `of` construct. See the `updateContext` for 6000 // `tt.name`. 6001 if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed) 6002 { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } 6003 if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow) 6004 { return true } 6005 if (prevType === types$1.braceL) 6006 { return parent === types.b_stat } 6007 if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name) 6008 { return false } 6009 return !this.exprAllowed 6010 }; 6011 6012 pp$6.inGeneratorContext = function() { 6013 for (var i = this.context.length - 1; i >= 1; i--) { 6014 var context = this.context[i]; 6015 if (context.token === "function") 6016 { return context.generator } 6017 } 6018 return false 6019 }; 6020 6021 pp$6.updateContext = function(prevType) { 6022 var update, type = this.type; 6023 if (type.keyword && prevType === types$1.dot) 6024 { this.exprAllowed = false; } 6025 else if (update = type.updateContext) 6026 { update.call(this, prevType); } 6027 else 6028 { this.exprAllowed = type.beforeExpr; } 6029 }; 6030 6031 // Used to handle egde cases when token context could not be inferred correctly during tokenization phase 6032 6033 pp$6.overrideContext = function(tokenCtx) { 6034 if (this.curContext() !== tokenCtx) { 6035 this.context[this.context.length - 1] = tokenCtx; 6036 } 6037 }; 6038 6039 // Token-specific context update code 6040 6041 types$1.parenR.updateContext = types$1.braceR.updateContext = function() { 6042 if (this.context.length === 1) { 6043 this.exprAllowed = true; 6044 return 6045 } 6046 var out = this.context.pop(); 6047 if (out === types.b_stat && this.curContext().token === "function") { 6048 out = this.context.pop(); 6049 } 6050 this.exprAllowed = !out.isExpr; 6051 }; 6052 6053 types$1.braceL.updateContext = function(prevType) { 6054 this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); 6055 this.exprAllowed = true; 6056 }; 6057 6058 types$1.dollarBraceL.updateContext = function() { 6059 this.context.push(types.b_tmpl); 6060 this.exprAllowed = true; 6061 }; 6062 6063 types$1.parenL.updateContext = function(prevType) { 6064 var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while; 6065 this.context.push(statementParens ? types.p_stat : types.p_expr); 6066 this.exprAllowed = true; 6067 }; 6068 6069 types$1.incDec.updateContext = function() { 6070 // tokExprAllowed stays unchanged 6071 }; 6072 6073 types$1._function.updateContext = types$1._class.updateContext = function(prevType) { 6074 if (prevType.beforeExpr && prevType !== types$1._else && 6075 !(prevType === types$1.semi && this.curContext() !== types.p_stat) && 6076 !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && 6077 !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat)) 6078 { this.context.push(types.f_expr); } 6079 else 6080 { this.context.push(types.f_stat); } 6081 this.exprAllowed = false; 6082 }; 6083 6084 types$1.backQuote.updateContext = function() { 6085 if (this.curContext() === types.q_tmpl) 6086 { this.context.pop(); } 6087 else 6088 { this.context.push(types.q_tmpl); } 6089 this.exprAllowed = false; 6090 }; 6091 6092 types$1.star.updateContext = function(prevType) { 6093 if (prevType === types$1._function) { 6094 var index = this.context.length - 1; 6095 if (this.context[index] === types.f_expr) 6096 { this.context[index] = types.f_expr_gen; } 6097 else 6098 { this.context[index] = types.f_gen; } 6099 } 6100 this.exprAllowed = true; 6101 }; 6102 6103 types$1.name.updateContext = function(prevType) { 6104 var allowed = false; 6105 if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) { 6106 if (this.value === "of" && !this.exprAllowed || 6107 this.value === "yield" && this.inGeneratorContext()) 6108 { allowed = true; } 6109 } 6110 this.exprAllowed = allowed; 6111 }; 6112 6113 // A recursive descent parser operates by defining functions for all 6114 6115 var pp$5 = Parser.prototype; 6116 6117 // Check if property name clashes with already added. 6118 // Object/class getters and setters are not allowed to clash — 6119 // either with each other or with an init property — and in 6120 // strict mode, init properties are also not allowed to be repeated. 6121 6122 pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) { 6123 if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") 6124 { return } 6125 if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) 6126 { return } 6127 var key = prop.key; 6128 var name; 6129 switch (key.type) { 6130 case "Identifier": name = key.name; break 6131 case "Literal": name = String(key.value); break 6132 default: return 6133 } 6134 var kind = prop.kind; 6135 if (this.options.ecmaVersion >= 6) { 6136 if (name === "__proto__" && kind === "init") { 6137 if (propHash.proto) { 6138 if (refDestructuringErrors) { 6139 if (refDestructuringErrors.doubleProto < 0) { 6140 refDestructuringErrors.doubleProto = key.start; 6141 } 6142 } else { 6143 this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); 6144 } 6145 } 6146 propHash.proto = true; 6147 } 6148 return 6149 } 6150 name = "$" + name; 6151 var other = propHash[name]; 6152 if (other) { 6153 var redefinition; 6154 if (kind === "init") { 6155 redefinition = this.strict && other.init || other.get || other.set; 6156 } else { 6157 redefinition = other.init || other[kind]; 6158 } 6159 if (redefinition) 6160 { this.raiseRecoverable(key.start, "Redefinition of property"); } 6161 } else { 6162 other = propHash[name] = { 6163 init: false, 6164 get: false, 6165 set: false 6166 }; 6167 } 6168 other[kind] = true; 6169 }; 6170 6171 // ### Expression parsing 6172 6173 // These nest, from the most general expression type at the top to 6174 // 'atomic', nondivisible expression types at the bottom. Most of 6175 // the functions will simply let the function(s) below them parse, 6176 // and, *if* the syntactic construct they handle is present, wrap 6177 // the AST node that the inner parser gave them in another node. 6178 6179 // Parse a full expression. The optional arguments are used to 6180 // forbid the `in` operator (in for loops initalization expressions) 6181 // and provide reference for storing '=' operator inside shorthand 6182 // property assignment in contexts where both object expression 6183 // and object pattern might appear (so it's possible to raise 6184 // delayed syntax error at correct position). 6185 6186 pp$5.parseExpression = function(forInit, refDestructuringErrors) { 6187 var startPos = this.start, startLoc = this.startLoc; 6188 var expr = this.parseMaybeAssign(forInit, refDestructuringErrors); 6189 if (this.type === types$1.comma) { 6190 var node = this.startNodeAt(startPos, startLoc); 6191 node.expressions = [expr]; 6192 while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); } 6193 return this.finishNode(node, "SequenceExpression") 6194 } 6195 return expr 6196 }; 6197 6198 // Parse an assignment expression. This includes applications of 6199 // operators like `+=`. 6200 6201 pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) { 6202 if (this.isContextual("yield")) { 6203 if (this.inGenerator) { return this.parseYield(forInit) } 6204 // The tokenizer will assume an expression is allowed after 6205 // `yield`, but this isn't that kind of yield 6206 else { this.exprAllowed = false; } 6207 } 6208 6209 var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1; 6210 if (refDestructuringErrors) { 6211 oldParenAssign = refDestructuringErrors.parenthesizedAssign; 6212 oldTrailingComma = refDestructuringErrors.trailingComma; 6213 oldDoubleProto = refDestructuringErrors.doubleProto; 6214 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; 6215 } else { 6216 refDestructuringErrors = new DestructuringErrors; 6217 ownDestructuringErrors = true; 6218 } 6219 6220 var startPos = this.start, startLoc = this.startLoc; 6221 if (this.type === types$1.parenL || this.type === types$1.name) { 6222 this.potentialArrowAt = this.start; 6223 this.potentialArrowInForAwait = forInit === "await"; 6224 } 6225 var left = this.parseMaybeConditional(forInit, refDestructuringErrors); 6226 if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } 6227 if (this.type.isAssign) { 6228 var node = this.startNodeAt(startPos, startLoc); 6229 node.operator = this.value; 6230 if (this.type === types$1.eq) 6231 { left = this.toAssignable(left, false, refDestructuringErrors); } 6232 if (!ownDestructuringErrors) { 6233 refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; 6234 } 6235 if (refDestructuringErrors.shorthandAssign >= left.start) 6236 { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly 6237 if (this.type === types$1.eq) 6238 { this.checkLValPattern(left); } 6239 else 6240 { this.checkLValSimple(left); } 6241 node.left = left; 6242 this.next(); 6243 node.right = this.parseMaybeAssign(forInit); 6244 if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; } 6245 return this.finishNode(node, "AssignmentExpression") 6246 } else { 6247 if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } 6248 } 6249 if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } 6250 if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } 6251 return left 6252 }; 6253 6254 // Parse a ternary conditional (`?:`) operator. 6255 6256 pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) { 6257 var startPos = this.start, startLoc = this.startLoc; 6258 var expr = this.parseExprOps(forInit, refDestructuringErrors); 6259 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } 6260 if (this.eat(types$1.question)) { 6261 var node = this.startNodeAt(startPos, startLoc); 6262 node.test = expr; 6263 node.consequent = this.parseMaybeAssign(); 6264 this.expect(types$1.colon); 6265 node.alternate = this.parseMaybeAssign(forInit); 6266 return this.finishNode(node, "ConditionalExpression") 6267 } 6268 return expr 6269 }; 6270 6271 // Start the precedence parser. 6272 6273 pp$5.parseExprOps = function(forInit, refDestructuringErrors) { 6274 var startPos = this.start, startLoc = this.startLoc; 6275 var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit); 6276 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } 6277 return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit) 6278 }; 6279 6280 // Parse binary operators with the operator precedence parsing 6281 // algorithm. `left` is the left-hand side of the operator. 6282 // `minPrec` provides context that allows the function to stop and 6283 // defer further parser to one of its callers when it encounters an 6284 // operator that has a lower precedence than the set it is parsing. 6285 6286 pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) { 6287 var prec = this.type.binop; 6288 if (prec != null && (!forInit || this.type !== types$1._in)) { 6289 if (prec > minPrec) { 6290 var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND; 6291 var coalesce = this.type === types$1.coalesce; 6292 if (coalesce) { 6293 // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. 6294 // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. 6295 prec = types$1.logicalAND.binop; 6296 } 6297 var op = this.value; 6298 this.next(); 6299 var startPos = this.start, startLoc = this.startLoc; 6300 var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit); 6301 var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); 6302 if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) { 6303 this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); 6304 } 6305 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit) 6306 } 6307 } 6308 return left 6309 }; 6310 6311 pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) { 6312 if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); } 6313 var node = this.startNodeAt(startPos, startLoc); 6314 node.left = left; 6315 node.operator = op; 6316 node.right = right; 6317 return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") 6318 }; 6319 6320 // Parse unary operators, both prefix and postfix. 6321 6322 pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) { 6323 var startPos = this.start, startLoc = this.startLoc, expr; 6324 if (this.isContextual("await") && this.canAwait) { 6325 expr = this.parseAwait(forInit); 6326 sawUnary = true; 6327 } else if (this.type.prefix) { 6328 var node = this.startNode(), update = this.type === types$1.incDec; 6329 node.operator = this.value; 6330 node.prefix = true; 6331 this.next(); 6332 node.argument = this.parseMaybeUnary(null, true, update, forInit); 6333 this.checkExpressionErrors(refDestructuringErrors, true); 6334 if (update) { this.checkLValSimple(node.argument); } 6335 else if (this.strict && node.operator === "delete" && 6336 node.argument.type === "Identifier") 6337 { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } 6338 else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) 6339 { this.raiseRecoverable(node.start, "Private fields can not be deleted"); } 6340 else { sawUnary = true; } 6341 expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); 6342 } else if (!sawUnary && this.type === types$1.privateId) { 6343 if (forInit || this.privateNameStack.length === 0) { this.unexpected(); } 6344 expr = this.parsePrivateIdent(); 6345 // only could be private fields in 'in', such as #x in obj 6346 if (this.type !== types$1._in) { this.unexpected(); } 6347 } else { 6348 expr = this.parseExprSubscripts(refDestructuringErrors, forInit); 6349 if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } 6350 while (this.type.postfix && !this.canInsertSemicolon()) { 6351 var node$1 = this.startNodeAt(startPos, startLoc); 6352 node$1.operator = this.value; 6353 node$1.prefix = false; 6354 node$1.argument = expr; 6355 this.checkLValSimple(expr); 6356 this.next(); 6357 expr = this.finishNode(node$1, "UpdateExpression"); 6358 } 6359 } 6360 6361 if (!incDec && this.eat(types$1.starstar)) { 6362 if (sawUnary) 6363 { this.unexpected(this.lastTokStart); } 6364 else 6365 { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) } 6366 } else { 6367 return expr 6368 } 6369 }; 6370 6371 function isPrivateFieldAccess(node) { 6372 return ( 6373 node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || 6374 node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) 6375 ) 6376 } 6377 6378 // Parse call, dot, and `[]`-subscript expressions. 6379 6380 pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) { 6381 var startPos = this.start, startLoc = this.startLoc; 6382 var expr = this.parseExprAtom(refDestructuringErrors, forInit); 6383 if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") 6384 { return expr } 6385 var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit); 6386 if (refDestructuringErrors && result.type === "MemberExpression") { 6387 if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } 6388 if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } 6389 if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; } 6390 } 6391 return result 6392 }; 6393 6394 pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) { 6395 var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && 6396 this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && 6397 this.potentialArrowAt === base.start; 6398 var optionalChained = false; 6399 6400 while (true) { 6401 var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit); 6402 6403 if (element.optional) { optionalChained = true; } 6404 if (element === base || element.type === "ArrowFunctionExpression") { 6405 if (optionalChained) { 6406 var chainNode = this.startNodeAt(startPos, startLoc); 6407 chainNode.expression = element; 6408 element = this.finishNode(chainNode, "ChainExpression"); 6409 } 6410 return element 6411 } 6412 6413 base = element; 6414 } 6415 }; 6416 6417 pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) { 6418 var optionalSupported = this.options.ecmaVersion >= 11; 6419 var optional = optionalSupported && this.eat(types$1.questionDot); 6420 if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } 6421 6422 var computed = this.eat(types$1.bracketL); 6423 if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) { 6424 var node = this.startNodeAt(startPos, startLoc); 6425 node.object = base; 6426 if (computed) { 6427 node.property = this.parseExpression(); 6428 this.expect(types$1.bracketR); 6429 } else if (this.type === types$1.privateId && base.type !== "Super") { 6430 node.property = this.parsePrivateIdent(); 6431 } else { 6432 node.property = this.parseIdent(this.options.allowReserved !== "never"); 6433 } 6434 node.computed = !!computed; 6435 if (optionalSupported) { 6436 node.optional = optional; 6437 } 6438 base = this.finishNode(node, "MemberExpression"); 6439 } else if (!noCalls && this.eat(types$1.parenL)) { 6440 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; 6441 this.yieldPos = 0; 6442 this.awaitPos = 0; 6443 this.awaitIdentPos = 0; 6444 var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); 6445 if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(types$1.arrow)) { 6446 this.checkPatternErrors(refDestructuringErrors, false); 6447 this.checkYieldAwaitInDefaultParams(); 6448 if (this.awaitIdentPos > 0) 6449 { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } 6450 this.yieldPos = oldYieldPos; 6451 this.awaitPos = oldAwaitPos; 6452 this.awaitIdentPos = oldAwaitIdentPos; 6453 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit) 6454 } 6455 this.checkExpressionErrors(refDestructuringErrors, true); 6456 this.yieldPos = oldYieldPos || this.yieldPos; 6457 this.awaitPos = oldAwaitPos || this.awaitPos; 6458 this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; 6459 var node$1 = this.startNodeAt(startPos, startLoc); 6460 node$1.callee = base; 6461 node$1.arguments = exprList; 6462 if (optionalSupported) { 6463 node$1.optional = optional; 6464 } 6465 base = this.finishNode(node$1, "CallExpression"); 6466 } else if (this.type === types$1.backQuote) { 6467 if (optional || optionalChained) { 6468 this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); 6469 } 6470 var node$2 = this.startNodeAt(startPos, startLoc); 6471 node$2.tag = base; 6472 node$2.quasi = this.parseTemplate({isTagged: true}); 6473 base = this.finishNode(node$2, "TaggedTemplateExpression"); 6474 } 6475 return base 6476 }; 6477 6478 // Parse an atomic expression — either a single token that is an 6479 // expression, an expression started by a keyword like `function` or 6480 // `new`, or an expression wrapped in punctuation like `()`, `[]`, 6481 // or `{}`. 6482 6483 pp$5.parseExprAtom = function(refDestructuringErrors, forInit) { 6484 // If a division operator appears in an expression position, the 6485 // tokenizer got confused, and we force it to read a regexp instead. 6486 if (this.type === types$1.slash) { this.readRegexp(); } 6487 6488 var node, canBeArrow = this.potentialArrowAt === this.start; 6489 switch (this.type) { 6490 case types$1._super: 6491 if (!this.allowSuper) 6492 { this.raise(this.start, "'super' keyword outside a method"); } 6493 node = this.startNode(); 6494 this.next(); 6495 if (this.type === types$1.parenL && !this.allowDirectSuper) 6496 { this.raise(node.start, "super() call outside constructor of a subclass"); } 6497 // The `super` keyword can appear at below: 6498 // SuperProperty: 6499 // super [ Expression ] 6500 // super . IdentifierName 6501 // SuperCall: 6502 // super ( Arguments ) 6503 if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL) 6504 { this.unexpected(); } 6505 return this.finishNode(node, "Super") 6506 6507 case types$1._this: 6508 node = this.startNode(); 6509 this.next(); 6510 return this.finishNode(node, "ThisExpression") 6511 6512 case types$1.name: 6513 var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; 6514 var id = this.parseIdent(false); 6515 if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) { 6516 this.overrideContext(types.f_expr); 6517 return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit) 6518 } 6519 if (canBeArrow && !this.canInsertSemicolon()) { 6520 if (this.eat(types$1.arrow)) 6521 { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) } 6522 if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc && 6523 (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) { 6524 id = this.parseIdent(false); 6525 if (this.canInsertSemicolon() || !this.eat(types$1.arrow)) 6526 { this.unexpected(); } 6527 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit) 6528 } 6529 } 6530 return id 6531 6532 case types$1.regexp: 6533 var value = this.value; 6534 node = this.parseLiteral(value.value); 6535 node.regex = {pattern: value.pattern, flags: value.flags}; 6536 return node 6537 6538 case types$1.num: case types$1.string: 6539 return this.parseLiteral(this.value) 6540 6541 case types$1._null: case types$1._true: case types$1._false: 6542 node = this.startNode(); 6543 node.value = this.type === types$1._null ? null : this.type === types$1._true; 6544 node.raw = this.type.keyword; 6545 this.next(); 6546 return this.finishNode(node, "Literal") 6547 6548 case types$1.parenL: 6549 var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit); 6550 if (refDestructuringErrors) { 6551 if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) 6552 { refDestructuringErrors.parenthesizedAssign = start; } 6553 if (refDestructuringErrors.parenthesizedBind < 0) 6554 { refDestructuringErrors.parenthesizedBind = start; } 6555 } 6556 return expr 6557 6558 case types$1.bracketL: 6559 node = this.startNode(); 6560 this.next(); 6561 node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors); 6562 return this.finishNode(node, "ArrayExpression") 6563 6564 case types$1.braceL: 6565 this.overrideContext(types.b_expr); 6566 return this.parseObj(false, refDestructuringErrors) 6567 6568 case types$1._function: 6569 node = this.startNode(); 6570 this.next(); 6571 return this.parseFunction(node, 0) 6572 6573 case types$1._class: 6574 return this.parseClass(this.startNode(), false) 6575 6576 case types$1._new: 6577 return this.parseNew() 6578 6579 case types$1.backQuote: 6580 return this.parseTemplate() 6581 6582 case types$1._import: 6583 if (this.options.ecmaVersion >= 11) { 6584 return this.parseExprImport() 6585 } else { 6586 return this.unexpected() 6587 } 6588 6589 default: 6590 this.unexpected(); 6591 } 6592 }; 6593 6594 pp$5.parseExprImport = function() { 6595 var node = this.startNode(); 6596 6597 // Consume `import` as an identifier for `import.meta`. 6598 // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. 6599 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } 6600 var meta = this.parseIdent(true); 6601 6602 switch (this.type) { 6603 case types$1.parenL: 6604 return this.parseDynamicImport(node) 6605 case types$1.dot: 6606 node.meta = meta; 6607 return this.parseImportMeta(node) 6608 default: 6609 this.unexpected(); 6610 } 6611 }; 6612 6613 pp$5.parseDynamicImport = function(node) { 6614 this.next(); // skip `(` 6615 6616 // Parse node.source. 6617 node.source = this.parseMaybeAssign(); 6618 6619 // Verify ending. 6620 if (!this.eat(types$1.parenR)) { 6621 var errorPos = this.start; 6622 if (this.eat(types$1.comma) && this.eat(types$1.parenR)) { 6623 this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); 6624 } else { 6625 this.unexpected(errorPos); 6626 } 6627 } 6628 6629 return this.finishNode(node, "ImportExpression") 6630 }; 6631 6632 pp$5.parseImportMeta = function(node) { 6633 this.next(); // skip `.` 6634 6635 var containsEsc = this.containsEsc; 6636 node.property = this.parseIdent(true); 6637 6638 if (node.property.name !== "meta") 6639 { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } 6640 if (containsEsc) 6641 { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } 6642 if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere) 6643 { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } 6644 6645 return this.finishNode(node, "MetaProperty") 6646 }; 6647 6648 pp$5.parseLiteral = function(value) { 6649 var node = this.startNode(); 6650 node.value = value; 6651 node.raw = this.input.slice(this.start, this.end); 6652 if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1).replace(/_/g, ""); } 6653 this.next(); 6654 return this.finishNode(node, "Literal") 6655 }; 6656 6657 pp$5.parseParenExpression = function() { 6658 this.expect(types$1.parenL); 6659 var val = this.parseExpression(); 6660 this.expect(types$1.parenR); 6661 return val 6662 }; 6663 6664 pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) { 6665 var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; 6666 if (this.options.ecmaVersion >= 6) { 6667 this.next(); 6668 6669 var innerStartPos = this.start, innerStartLoc = this.startLoc; 6670 var exprList = [], first = true, lastIsComma = false; 6671 var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; 6672 this.yieldPos = 0; 6673 this.awaitPos = 0; 6674 // Do not save awaitIdentPos to allow checking awaits nested in parameters 6675 while (this.type !== types$1.parenR) { 6676 first ? first = false : this.expect(types$1.comma); 6677 if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) { 6678 lastIsComma = true; 6679 break 6680 } else if (this.type === types$1.ellipsis) { 6681 spreadStart = this.start; 6682 exprList.push(this.parseParenItem(this.parseRestBinding())); 6683 if (this.type === types$1.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } 6684 break 6685 } else { 6686 exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); 6687 } 6688 } 6689 var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; 6690 this.expect(types$1.parenR); 6691 6692 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types$1.arrow)) { 6693 this.checkPatternErrors(refDestructuringErrors, false); 6694 this.checkYieldAwaitInDefaultParams(); 6695 this.yieldPos = oldYieldPos; 6696 this.awaitPos = oldAwaitPos; 6697 return this.parseParenArrowList(startPos, startLoc, exprList, forInit) 6698 } 6699 6700 if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } 6701 if (spreadStart) { this.unexpected(spreadStart); } 6702 this.checkExpressionErrors(refDestructuringErrors, true); 6703 this.yieldPos = oldYieldPos || this.yieldPos; 6704 this.awaitPos = oldAwaitPos || this.awaitPos; 6705 6706 if (exprList.length > 1) { 6707 val = this.startNodeAt(innerStartPos, innerStartLoc); 6708 val.expressions = exprList; 6709 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); 6710 } else { 6711 val = exprList[0]; 6712 } 6713 } else { 6714 val = this.parseParenExpression(); 6715 } 6716 6717 if (this.options.preserveParens) { 6718 var par = this.startNodeAt(startPos, startLoc); 6719 par.expression = val; 6720 return this.finishNode(par, "ParenthesizedExpression") 6721 } else { 6722 return val 6723 } 6724 }; 6725 6726 pp$5.parseParenItem = function(item) { 6727 return item 6728 }; 6729 6730 pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) { 6731 return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit) 6732 }; 6733 6734 // New's precedence is slightly tricky. It must allow its argument to 6735 // be a `[]` or dot subscript expression, but not a call — at least, 6736 // not without wrapping it in parentheses. Thus, it uses the noCalls 6737 // argument to parseSubscripts to prevent it from consuming the 6738 // argument list. 6739 6740 var empty = []; 6741 6742 pp$5.parseNew = function() { 6743 if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } 6744 var node = this.startNode(); 6745 var meta = this.parseIdent(true); 6746 if (this.options.ecmaVersion >= 6 && this.eat(types$1.dot)) { 6747 node.meta = meta; 6748 var containsEsc = this.containsEsc; 6749 node.property = this.parseIdent(true); 6750 if (node.property.name !== "target") 6751 { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } 6752 if (containsEsc) 6753 { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } 6754 if (!this.allowNewDotTarget) 6755 { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); } 6756 return this.finishNode(node, "MetaProperty") 6757 } 6758 var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types$1._import; 6759 node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true, false); 6760 if (isImport && node.callee.type === "ImportExpression") { 6761 this.raise(startPos, "Cannot use new with import()"); 6762 } 6763 if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); } 6764 else { node.arguments = empty; } 6765 return this.finishNode(node, "NewExpression") 6766 }; 6767 6768 // Parse template expression. 6769 6770 pp$5.parseTemplateElement = function(ref) { 6771 var isTagged = ref.isTagged; 6772 6773 var elem = this.startNode(); 6774 if (this.type === types$1.invalidTemplate) { 6775 if (!isTagged) { 6776 this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); 6777 } 6778 elem.value = { 6779 raw: this.value, 6780 cooked: null 6781 }; 6782 } else { 6783 elem.value = { 6784 raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), 6785 cooked: this.value 6786 }; 6787 } 6788 this.next(); 6789 elem.tail = this.type === types$1.backQuote; 6790 return this.finishNode(elem, "TemplateElement") 6791 }; 6792 6793 pp$5.parseTemplate = function(ref) { 6794 if ( ref === void 0 ) ref = {}; 6795 var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; 6796 6797 var node = this.startNode(); 6798 this.next(); 6799 node.expressions = []; 6800 var curElt = this.parseTemplateElement({isTagged: isTagged}); 6801 node.quasis = [curElt]; 6802 while (!curElt.tail) { 6803 if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); } 6804 this.expect(types$1.dollarBraceL); 6805 node.expressions.push(this.parseExpression()); 6806 this.expect(types$1.braceR); 6807 node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); 6808 } 6809 this.next(); 6810 return this.finishNode(node, "TemplateLiteral") 6811 }; 6812 6813 pp$5.isAsyncProp = function(prop) { 6814 return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && 6815 (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) && 6816 !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) 6817 }; 6818 6819 // Parse an object literal or binding pattern. 6820 6821 pp$5.parseObj = function(isPattern, refDestructuringErrors) { 6822 var node = this.startNode(), first = true, propHash = {}; 6823 node.properties = []; 6824 this.next(); 6825 while (!this.eat(types$1.braceR)) { 6826 if (!first) { 6827 this.expect(types$1.comma); 6828 if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break } 6829 } else { first = false; } 6830 6831 var prop = this.parseProperty(isPattern, refDestructuringErrors); 6832 if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } 6833 node.properties.push(prop); 6834 } 6835 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") 6836 }; 6837 6838 pp$5.parseProperty = function(isPattern, refDestructuringErrors) { 6839 var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; 6840 if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) { 6841 if (isPattern) { 6842 prop.argument = this.parseIdent(false); 6843 if (this.type === types$1.comma) { 6844 this.raise(this.start, "Comma is not permitted after the rest element"); 6845 } 6846 return this.finishNode(prop, "RestElement") 6847 } 6848 // Parse argument. 6849 prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); 6850 // To disallow trailing comma via `this.toAssignable()`. 6851 if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { 6852 refDestructuringErrors.trailingComma = this.start; 6853 } 6854 // Finish 6855 return this.finishNode(prop, "SpreadElement") 6856 } 6857 if (this.options.ecmaVersion >= 6) { 6858 prop.method = false; 6859 prop.shorthand = false; 6860 if (isPattern || refDestructuringErrors) { 6861 startPos = this.start; 6862 startLoc = this.startLoc; 6863 } 6864 if (!isPattern) 6865 { isGenerator = this.eat(types$1.star); } 6866 } 6867 var containsEsc = this.containsEsc; 6868 this.parsePropertyName(prop); 6869 if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { 6870 isAsync = true; 6871 isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star); 6872 this.parsePropertyName(prop); 6873 } else { 6874 isAsync = false; 6875 } 6876 this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); 6877 return this.finishNode(prop, "Property") 6878 }; 6879 6880 pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { 6881 if ((isGenerator || isAsync) && this.type === types$1.colon) 6882 { this.unexpected(); } 6883 6884 if (this.eat(types$1.colon)) { 6885 prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); 6886 prop.kind = "init"; 6887 } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) { 6888 if (isPattern) { this.unexpected(); } 6889 prop.kind = "init"; 6890 prop.method = true; 6891 prop.value = this.parseMethod(isGenerator, isAsync); 6892 } else if (!isPattern && !containsEsc && 6893 this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && 6894 (prop.key.name === "get" || prop.key.name === "set") && 6895 (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) { 6896 if (isGenerator || isAsync) { this.unexpected(); } 6897 prop.kind = prop.key.name; 6898 this.parsePropertyName(prop); 6899 prop.value = this.parseMethod(false); 6900 var paramCount = prop.kind === "get" ? 0 : 1; 6901 if (prop.value.params.length !== paramCount) { 6902 var start = prop.value.start; 6903 if (prop.kind === "get") 6904 { this.raiseRecoverable(start, "getter should have no params"); } 6905 else 6906 { this.raiseRecoverable(start, "setter should have exactly one param"); } 6907 } else { 6908 if (prop.kind === "set" && prop.value.params[0].type === "RestElement") 6909 { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } 6910 } 6911 } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { 6912 if (isGenerator || isAsync) { this.unexpected(); } 6913 this.checkUnreserved(prop.key); 6914 if (prop.key.name === "await" && !this.awaitIdentPos) 6915 { this.awaitIdentPos = startPos; } 6916 prop.kind = "init"; 6917 if (isPattern) { 6918 prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); 6919 } else if (this.type === types$1.eq && refDestructuringErrors) { 6920 if (refDestructuringErrors.shorthandAssign < 0) 6921 { refDestructuringErrors.shorthandAssign = this.start; } 6922 prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); 6923 } else { 6924 prop.value = this.copyNode(prop.key); 6925 } 6926 prop.shorthand = true; 6927 } else { this.unexpected(); } 6928 }; 6929 6930 pp$5.parsePropertyName = function(prop) { 6931 if (this.options.ecmaVersion >= 6) { 6932 if (this.eat(types$1.bracketL)) { 6933 prop.computed = true; 6934 prop.key = this.parseMaybeAssign(); 6935 this.expect(types$1.bracketR); 6936 return prop.key 6937 } else { 6938 prop.computed = false; 6939 } 6940 } 6941 return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") 6942 }; 6943 6944 // Initialize empty function node. 6945 6946 pp$5.initFunction = function(node) { 6947 node.id = null; 6948 if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } 6949 if (this.options.ecmaVersion >= 8) { node.async = false; } 6950 }; 6951 6952 // Parse object or class method. 6953 6954 pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { 6955 var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; 6956 6957 this.initFunction(node); 6958 if (this.options.ecmaVersion >= 6) 6959 { node.generator = isGenerator; } 6960 if (this.options.ecmaVersion >= 8) 6961 { node.async = !!isAsync; } 6962 6963 this.yieldPos = 0; 6964 this.awaitPos = 0; 6965 this.awaitIdentPos = 0; 6966 this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); 6967 6968 this.expect(types$1.parenL); 6969 node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); 6970 this.checkYieldAwaitInDefaultParams(); 6971 this.parseFunctionBody(node, false, true, false); 6972 6973 this.yieldPos = oldYieldPos; 6974 this.awaitPos = oldAwaitPos; 6975 this.awaitIdentPos = oldAwaitIdentPos; 6976 return this.finishNode(node, "FunctionExpression") 6977 }; 6978 6979 // Parse arrow function expression with given parameters. 6980 6981 pp$5.parseArrowExpression = function(node, params, isAsync, forInit) { 6982 var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; 6983 6984 this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); 6985 this.initFunction(node); 6986 if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } 6987 6988 this.yieldPos = 0; 6989 this.awaitPos = 0; 6990 this.awaitIdentPos = 0; 6991 6992 node.params = this.toAssignableList(params, true); 6993 this.parseFunctionBody(node, true, false, forInit); 6994 6995 this.yieldPos = oldYieldPos; 6996 this.awaitPos = oldAwaitPos; 6997 this.awaitIdentPos = oldAwaitIdentPos; 6998 return this.finishNode(node, "ArrowFunctionExpression") 6999 }; 7000 7001 // Parse function body and check parameters. 7002 7003 pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) { 7004 var isExpression = isArrowFunction && this.type !== types$1.braceL; 7005 var oldStrict = this.strict, useStrict = false; 7006 7007 if (isExpression) { 7008 node.body = this.parseMaybeAssign(forInit); 7009 node.expression = true; 7010 this.checkParams(node, false); 7011 } else { 7012 var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); 7013 if (!oldStrict || nonSimple) { 7014 useStrict = this.strictDirective(this.end); 7015 // If this is a strict mode function, verify that argument names 7016 // are not repeated, and it does not try to bind the words `eval` 7017 // or `arguments`. 7018 if (useStrict && nonSimple) 7019 { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } 7020 } 7021 // Start a new scope with regard to labels and the `inFunction` 7022 // flag (restore them to their old value afterwards). 7023 var oldLabels = this.labels; 7024 this.labels = []; 7025 if (useStrict) { this.strict = true; } 7026 7027 // Add the params to varDeclaredNames to ensure that an error is thrown 7028 // if a let/const declaration in the function clashes with one of the params. 7029 this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); 7030 // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' 7031 if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); } 7032 node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); 7033 node.expression = false; 7034 this.adaptDirectivePrologue(node.body.body); 7035 this.labels = oldLabels; 7036 } 7037 this.exitScope(); 7038 }; 7039 7040 pp$5.isSimpleParamList = function(params) { 7041 for (var i = 0, list = params; i < list.length; i += 1) 7042 { 7043 var param = list[i]; 7044 7045 if (param.type !== "Identifier") { return false 7046 } } 7047 return true 7048 }; 7049 7050 // Checks function params for various disallowed patterns such as using "eval" 7051 // or "arguments" and duplicate parameters. 7052 7053 pp$5.checkParams = function(node, allowDuplicates) { 7054 var nameHash = Object.create(null); 7055 for (var i = 0, list = node.params; i < list.length; i += 1) 7056 { 7057 var param = list[i]; 7058 7059 this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash); 7060 } 7061 }; 7062 7063 // Parses a comma-separated list of expressions, and returns them as 7064 // an array. `close` is the token type that ends the list, and 7065 // `allowEmpty` can be turned on to allow subsequent commas with 7066 // nothing in between them to be parsed as `null` (which is needed 7067 // for array literals). 7068 7069 pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { 7070 var elts = [], first = true; 7071 while (!this.eat(close)) { 7072 if (!first) { 7073 this.expect(types$1.comma); 7074 if (allowTrailingComma && this.afterTrailingComma(close)) { break } 7075 } else { first = false; } 7076 7077 var elt = (void 0); 7078 if (allowEmpty && this.type === types$1.comma) 7079 { elt = null; } 7080 else if (this.type === types$1.ellipsis) { 7081 elt = this.parseSpread(refDestructuringErrors); 7082 if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0) 7083 { refDestructuringErrors.trailingComma = this.start; } 7084 } else { 7085 elt = this.parseMaybeAssign(false, refDestructuringErrors); 7086 } 7087 elts.push(elt); 7088 } 7089 return elts 7090 }; 7091 7092 pp$5.checkUnreserved = function(ref) { 7093 var start = ref.start; 7094 var end = ref.end; 7095 var name = ref.name; 7096 7097 if (this.inGenerator && name === "yield") 7098 { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } 7099 if (this.inAsync && name === "await") 7100 { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } 7101 if (this.currentThisScope().inClassFieldInit && name === "arguments") 7102 { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); } 7103 if (this.inClassStaticBlock && (name === "arguments" || name === "await")) 7104 { this.raise(start, ("Cannot use " + name + " in class static initialization block")); } 7105 if (this.keywords.test(name)) 7106 { this.raise(start, ("Unexpected keyword '" + name + "'")); } 7107 if (this.options.ecmaVersion < 6 && 7108 this.input.slice(start, end).indexOf("\\") !== -1) { return } 7109 var re = this.strict ? this.reservedWordsStrict : this.reservedWords; 7110 if (re.test(name)) { 7111 if (!this.inAsync && name === "await") 7112 { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } 7113 this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); 7114 } 7115 }; 7116 7117 // Parse the next token as an identifier. If `liberal` is true (used 7118 // when parsing properties), it will also convert keywords into 7119 // identifiers. 7120 7121 pp$5.parseIdent = function(liberal) { 7122 var node = this.startNode(); 7123 if (this.type === types$1.name) { 7124 node.name = this.value; 7125 } else if (this.type.keyword) { 7126 node.name = this.type.keyword; 7127 7128 // To fix https://github.com/acornjs/acorn/issues/575 7129 // `class` and `function` keywords push new context into this.context. 7130 // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. 7131 // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword 7132 if ((node.name === "class" || node.name === "function") && 7133 (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { 7134 this.context.pop(); 7135 } 7136 } else { 7137 this.unexpected(); 7138 } 7139 this.next(!!liberal); 7140 this.finishNode(node, "Identifier"); 7141 if (!liberal) { 7142 this.checkUnreserved(node); 7143 if (node.name === "await" && !this.awaitIdentPos) 7144 { this.awaitIdentPos = node.start; } 7145 } 7146 return node 7147 }; 7148 7149 pp$5.parsePrivateIdent = function() { 7150 var node = this.startNode(); 7151 if (this.type === types$1.privateId) { 7152 node.name = this.value; 7153 } else { 7154 this.unexpected(); 7155 } 7156 this.next(); 7157 this.finishNode(node, "PrivateIdentifier"); 7158 7159 // For validating existence 7160 if (this.privateNameStack.length === 0) { 7161 this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class")); 7162 } else { 7163 this.privateNameStack[this.privateNameStack.length - 1].used.push(node); 7164 } 7165 7166 return node 7167 }; 7168 7169 // Parses yield expression inside generator. 7170 7171 pp$5.parseYield = function(forInit) { 7172 if (!this.yieldPos) { this.yieldPos = this.start; } 7173 7174 var node = this.startNode(); 7175 this.next(); 7176 if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) { 7177 node.delegate = false; 7178 node.argument = null; 7179 } else { 7180 node.delegate = this.eat(types$1.star); 7181 node.argument = this.parseMaybeAssign(forInit); 7182 } 7183 return this.finishNode(node, "YieldExpression") 7184 }; 7185 7186 pp$5.parseAwait = function(forInit) { 7187 if (!this.awaitPos) { this.awaitPos = this.start; } 7188 7189 var node = this.startNode(); 7190 this.next(); 7191 node.argument = this.parseMaybeUnary(null, true, false, forInit); 7192 return this.finishNode(node, "AwaitExpression") 7193 }; 7194 7195 var pp$4 = Parser.prototype; 7196 7197 // This function is used to raise exceptions on parse errors. It 7198 // takes an offset integer (into the current `input`) to indicate 7199 // the location of the error, attaches the position to the end 7200 // of the error message, and then raises a `SyntaxError` with that 7201 // message. 7202 7203 pp$4.raise = function(pos, message) { 7204 var loc = getLineInfo(this.input, pos); 7205 message += " (" + loc.line + ":" + loc.column + ")"; 7206 var err = new SyntaxError(message); 7207 err.pos = pos; err.loc = loc; err.raisedAt = this.pos; 7208 throw err 7209 }; 7210 7211 pp$4.raiseRecoverable = pp$4.raise; 7212 7213 pp$4.curPosition = function() { 7214 if (this.options.locations) { 7215 return new Position(this.curLine, this.pos - this.lineStart) 7216 } 7217 }; 7218 7219 var pp$3 = Parser.prototype; 7220 7221 var Scope = function Scope(flags) { 7222 this.flags = flags; 7223 // A list of var-declared names in the current lexical scope 7224 this.var = []; 7225 // A list of lexically-declared names in the current lexical scope 7226 this.lexical = []; 7227 // A list of lexically-declared FunctionDeclaration names in the current lexical scope 7228 this.functions = []; 7229 // A switch to disallow the identifier reference 'arguments' 7230 this.inClassFieldInit = false; 7231 }; 7232 7233 // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. 7234 7235 pp$3.enterScope = function(flags) { 7236 this.scopeStack.push(new Scope(flags)); 7237 }; 7238 7239 pp$3.exitScope = function() { 7240 this.scopeStack.pop(); 7241 }; 7242 7243 // The spec says: 7244 // > At the top level of a function, or script, function declarations are 7245 // > treated like var declarations rather than like lexical declarations. 7246 pp$3.treatFunctionsAsVarInScope = function(scope) { 7247 return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) 7248 }; 7249 7250 pp$3.declareName = function(name, bindingType, pos) { 7251 var redeclared = false; 7252 if (bindingType === BIND_LEXICAL) { 7253 var scope = this.currentScope(); 7254 redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; 7255 scope.lexical.push(name); 7256 if (this.inModule && (scope.flags & SCOPE_TOP)) 7257 { delete this.undefinedExports[name]; } 7258 } else if (bindingType === BIND_SIMPLE_CATCH) { 7259 var scope$1 = this.currentScope(); 7260 scope$1.lexical.push(name); 7261 } else if (bindingType === BIND_FUNCTION) { 7262 var scope$2 = this.currentScope(); 7263 if (this.treatFunctionsAsVar) 7264 { redeclared = scope$2.lexical.indexOf(name) > -1; } 7265 else 7266 { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } 7267 scope$2.functions.push(name); 7268 } else { 7269 for (var i = this.scopeStack.length - 1; i >= 0; --i) { 7270 var scope$3 = this.scopeStack[i]; 7271 if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || 7272 !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { 7273 redeclared = true; 7274 break 7275 } 7276 scope$3.var.push(name); 7277 if (this.inModule && (scope$3.flags & SCOPE_TOP)) 7278 { delete this.undefinedExports[name]; } 7279 if (scope$3.flags & SCOPE_VAR) { break } 7280 } 7281 } 7282 if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } 7283 }; 7284 7285 pp$3.checkLocalExport = function(id) { 7286 // scope.functions must be empty as Module code is always strict. 7287 if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && 7288 this.scopeStack[0].var.indexOf(id.name) === -1) { 7289 this.undefinedExports[id.name] = id; 7290 } 7291 }; 7292 7293 pp$3.currentScope = function() { 7294 return this.scopeStack[this.scopeStack.length - 1] 7295 }; 7296 7297 pp$3.currentVarScope = function() { 7298 for (var i = this.scopeStack.length - 1;; i--) { 7299 var scope = this.scopeStack[i]; 7300 if (scope.flags & SCOPE_VAR) { return scope } 7301 } 7302 }; 7303 7304 // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. 7305 pp$3.currentThisScope = function() { 7306 for (var i = this.scopeStack.length - 1;; i--) { 7307 var scope = this.scopeStack[i]; 7308 if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope } 7309 } 7310 }; 7311 7312 var Node = function Node(parser, pos, loc) { 7313 this.type = ""; 7314 this.start = pos; 7315 this.end = 0; 7316 if (parser.options.locations) 7317 { this.loc = new SourceLocation(parser, loc); } 7318 if (parser.options.directSourceFile) 7319 { this.sourceFile = parser.options.directSourceFile; } 7320 if (parser.options.ranges) 7321 { this.range = [pos, 0]; } 7322 }; 7323 7324 // Start an AST node, attaching a start offset. 7325 7326 var pp$2 = Parser.prototype; 7327 7328 pp$2.startNode = function() { 7329 return new Node(this, this.start, this.startLoc) 7330 }; 7331 7332 pp$2.startNodeAt = function(pos, loc) { 7333 return new Node(this, pos, loc) 7334 }; 7335 7336 // Finish an AST node, adding `type` and `end` properties. 7337 7338 function finishNodeAt(node, type, pos, loc) { 7339 node.type = type; 7340 node.end = pos; 7341 if (this.options.locations) 7342 { node.loc.end = loc; } 7343 if (this.options.ranges) 7344 { node.range[1] = pos; } 7345 return node 7346 } 7347 7348 pp$2.finishNode = function(node, type) { 7349 return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) 7350 }; 7351 7352 // Finish node at given position 7353 7354 pp$2.finishNodeAt = function(node, type, pos, loc) { 7355 return finishNodeAt.call(this, node, type, pos, loc) 7356 }; 7357 7358 pp$2.copyNode = function(node) { 7359 var newNode = new Node(this, node.start, this.startLoc); 7360 for (var prop in node) { newNode[prop] = node[prop]; } 7361 return newNode 7362 }; 7363 7364 // This file contains Unicode properties extracted from the ECMAScript specification. 7365 // The lists are extracted like so: 7366 // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) 7367 7368 // #table-binary-unicode-properties 7369 var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; 7370 var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; 7371 var ecma11BinaryProperties = ecma10BinaryProperties; 7372 var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict"; 7373 var ecma13BinaryProperties = ecma12BinaryProperties; 7374 var ecma14BinaryProperties = ecma13BinaryProperties; 7375 7376 var unicodeBinaryProperties = { 7377 9: ecma9BinaryProperties, 7378 10: ecma10BinaryProperties, 7379 11: ecma11BinaryProperties, 7380 12: ecma12BinaryProperties, 7381 13: ecma13BinaryProperties, 7382 14: ecma14BinaryProperties 7383 }; 7384 7385 // #table-unicode-general-category-values 7386 var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; 7387 7388 // #table-unicode-script-values 7389 var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; 7390 var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; 7391 var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; 7392 var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi"; 7393 var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith"; 7394 var ecma14ScriptValues = ecma13ScriptValues + " Kawi Nag_Mundari Nagm"; 7395 7396 var unicodeScriptValues = { 7397 9: ecma9ScriptValues, 7398 10: ecma10ScriptValues, 7399 11: ecma11ScriptValues, 7400 12: ecma12ScriptValues, 7401 13: ecma13ScriptValues, 7402 14: ecma14ScriptValues 7403 }; 7404 7405 var data = {}; 7406 function buildUnicodeData(ecmaVersion) { 7407 var d = data[ecmaVersion] = { 7408 binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), 7409 nonBinary: { 7410 General_Category: wordsRegexp(unicodeGeneralCategoryValues), 7411 Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) 7412 } 7413 }; 7414 d.nonBinary.Script_Extensions = d.nonBinary.Script; 7415 7416 d.nonBinary.gc = d.nonBinary.General_Category; 7417 d.nonBinary.sc = d.nonBinary.Script; 7418 d.nonBinary.scx = d.nonBinary.Script_Extensions; 7419 } 7420 7421 for (var i = 0, list = [9, 10, 11, 12, 13, 14]; i < list.length; i += 1) { 7422 var ecmaVersion = list[i]; 7423 7424 buildUnicodeData(ecmaVersion); 7425 } 7426 7427 var pp$1 = Parser.prototype; 7428 7429 var RegExpValidationState = function RegExpValidationState(parser) { 7430 this.parser = parser; 7431 this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : ""); 7432 this.unicodeProperties = data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion]; 7433 this.source = ""; 7434 this.flags = ""; 7435 this.start = 0; 7436 this.switchU = false; 7437 this.switchN = false; 7438 this.pos = 0; 7439 this.lastIntValue = 0; 7440 this.lastStringValue = ""; 7441 this.lastAssertionIsQuantifiable = false; 7442 this.numCapturingParens = 0; 7443 this.maxBackReference = 0; 7444 this.groupNames = []; 7445 this.backReferenceNames = []; 7446 }; 7447 7448 RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { 7449 var unicode = flags.indexOf("u") !== -1; 7450 this.start = start | 0; 7451 this.source = pattern + ""; 7452 this.flags = flags; 7453 this.switchU = unicode && this.parser.options.ecmaVersion >= 6; 7454 this.switchN = unicode && this.parser.options.ecmaVersion >= 9; 7455 }; 7456 7457 RegExpValidationState.prototype.raise = function raise (message) { 7458 this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); 7459 }; 7460 7461 // If u flag is given, this returns the code point at the index (it combines a surrogate pair). 7462 // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). 7463 RegExpValidationState.prototype.at = function at (i, forceU) { 7464 if ( forceU === void 0 ) forceU = false; 7465 7466 var s = this.source; 7467 var l = s.length; 7468 if (i >= l) { 7469 return -1 7470 } 7471 var c = s.charCodeAt(i); 7472 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { 7473 return c 7474 } 7475 var next = s.charCodeAt(i + 1); 7476 return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c 7477 }; 7478 7479 RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { 7480 if ( forceU === void 0 ) forceU = false; 7481 7482 var s = this.source; 7483 var l = s.length; 7484 if (i >= l) { 7485 return l 7486 } 7487 var c = s.charCodeAt(i), next; 7488 if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || 7489 (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { 7490 return i + 1 7491 } 7492 return i + 2 7493 }; 7494 7495 RegExpValidationState.prototype.current = function current (forceU) { 7496 if ( forceU === void 0 ) forceU = false; 7497 7498 return this.at(this.pos, forceU) 7499 }; 7500 7501 RegExpValidationState.prototype.lookahead = function lookahead (forceU) { 7502 if ( forceU === void 0 ) forceU = false; 7503 7504 return this.at(this.nextIndex(this.pos, forceU), forceU) 7505 }; 7506 7507 RegExpValidationState.prototype.advance = function advance (forceU) { 7508 if ( forceU === void 0 ) forceU = false; 7509 7510 this.pos = this.nextIndex(this.pos, forceU); 7511 }; 7512 7513 RegExpValidationState.prototype.eat = function eat (ch, forceU) { 7514 if ( forceU === void 0 ) forceU = false; 7515 7516 if (this.current(forceU) === ch) { 7517 this.advance(forceU); 7518 return true 7519 } 7520 return false 7521 }; 7522 7523 /** 7524 * Validate the flags part of a given RegExpLiteral. 7525 * 7526 * @param {RegExpValidationState} state The state to validate RegExp. 7527 * @returns {void} 7528 */ 7529 pp$1.validateRegExpFlags = function(state) { 7530 var validFlags = state.validFlags; 7531 var flags = state.flags; 7532 7533 for (var i = 0; i < flags.length; i++) { 7534 var flag = flags.charAt(i); 7535 if (validFlags.indexOf(flag) === -1) { 7536 this.raise(state.start, "Invalid regular expression flag"); 7537 } 7538 if (flags.indexOf(flag, i + 1) > -1) { 7539 this.raise(state.start, "Duplicate regular expression flag"); 7540 } 7541 } 7542 }; 7543 7544 /** 7545 * Validate the pattern part of a given RegExpLiteral. 7546 * 7547 * @param {RegExpValidationState} state The state to validate RegExp. 7548 * @returns {void} 7549 */ 7550 pp$1.validateRegExpPattern = function(state) { 7551 this.regexp_pattern(state); 7552 7553 // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of 7554 // parsing contains a |GroupName|, reparse with the goal symbol 7555 // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* 7556 // exception if _P_ did not conform to the grammar, if any elements of _P_ 7557 // were not matched by the parse, or if any Early Error conditions exist. 7558 if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { 7559 state.switchN = true; 7560 this.regexp_pattern(state); 7561 } 7562 }; 7563 7564 // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern 7565 pp$1.regexp_pattern = function(state) { 7566 state.pos = 0; 7567 state.lastIntValue = 0; 7568 state.lastStringValue = ""; 7569 state.lastAssertionIsQuantifiable = false; 7570 state.numCapturingParens = 0; 7571 state.maxBackReference = 0; 7572 state.groupNames.length = 0; 7573 state.backReferenceNames.length = 0; 7574 7575 this.regexp_disjunction(state); 7576 7577 if (state.pos !== state.source.length) { 7578 // Make the same messages as V8. 7579 if (state.eat(0x29 /* ) */)) { 7580 state.raise("Unmatched ')'"); 7581 } 7582 if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { 7583 state.raise("Lone quantifier brackets"); 7584 } 7585 } 7586 if (state.maxBackReference > state.numCapturingParens) { 7587 state.raise("Invalid escape"); 7588 } 7589 for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { 7590 var name = list[i]; 7591 7592 if (state.groupNames.indexOf(name) === -1) { 7593 state.raise("Invalid named capture referenced"); 7594 } 7595 } 7596 }; 7597 7598 // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction 7599 pp$1.regexp_disjunction = function(state) { 7600 this.regexp_alternative(state); 7601 while (state.eat(0x7C /* | */)) { 7602 this.regexp_alternative(state); 7603 } 7604 7605 // Make the same message as V8. 7606 if (this.regexp_eatQuantifier(state, true)) { 7607 state.raise("Nothing to repeat"); 7608 } 7609 if (state.eat(0x7B /* { */)) { 7610 state.raise("Lone quantifier brackets"); 7611 } 7612 }; 7613 7614 // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative 7615 pp$1.regexp_alternative = function(state) { 7616 while (state.pos < state.source.length && this.regexp_eatTerm(state)) 7617 { } 7618 }; 7619 7620 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term 7621 pp$1.regexp_eatTerm = function(state) { 7622 if (this.regexp_eatAssertion(state)) { 7623 // Handle `QuantifiableAssertion Quantifier` alternative. 7624 // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion 7625 // is a QuantifiableAssertion. 7626 if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { 7627 // Make the same message as V8. 7628 if (state.switchU) { 7629 state.raise("Invalid quantifier"); 7630 } 7631 } 7632 return true 7633 } 7634 7635 if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { 7636 this.regexp_eatQuantifier(state); 7637 return true 7638 } 7639 7640 return false 7641 }; 7642 7643 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion 7644 pp$1.regexp_eatAssertion = function(state) { 7645 var start = state.pos; 7646 state.lastAssertionIsQuantifiable = false; 7647 7648 // ^, $ 7649 if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { 7650 return true 7651 } 7652 7653 // \b \B 7654 if (state.eat(0x5C /* \ */)) { 7655 if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { 7656 return true 7657 } 7658 state.pos = start; 7659 } 7660 7661 // Lookahead / Lookbehind 7662 if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { 7663 var lookbehind = false; 7664 if (this.options.ecmaVersion >= 9) { 7665 lookbehind = state.eat(0x3C /* < */); 7666 } 7667 if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { 7668 this.regexp_disjunction(state); 7669 if (!state.eat(0x29 /* ) */)) { 7670 state.raise("Unterminated group"); 7671 } 7672 state.lastAssertionIsQuantifiable = !lookbehind; 7673 return true 7674 } 7675 } 7676 7677 state.pos = start; 7678 return false 7679 }; 7680 7681 // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier 7682 pp$1.regexp_eatQuantifier = function(state, noError) { 7683 if ( noError === void 0 ) noError = false; 7684 7685 if (this.regexp_eatQuantifierPrefix(state, noError)) { 7686 state.eat(0x3F /* ? */); 7687 return true 7688 } 7689 return false 7690 }; 7691 7692 // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix 7693 pp$1.regexp_eatQuantifierPrefix = function(state, noError) { 7694 return ( 7695 state.eat(0x2A /* * */) || 7696 state.eat(0x2B /* + */) || 7697 state.eat(0x3F /* ? */) || 7698 this.regexp_eatBracedQuantifier(state, noError) 7699 ) 7700 }; 7701 pp$1.regexp_eatBracedQuantifier = function(state, noError) { 7702 var start = state.pos; 7703 if (state.eat(0x7B /* { */)) { 7704 var min = 0, max = -1; 7705 if (this.regexp_eatDecimalDigits(state)) { 7706 min = state.lastIntValue; 7707 if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { 7708 max = state.lastIntValue; 7709 } 7710 if (state.eat(0x7D /* } */)) { 7711 // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term 7712 if (max !== -1 && max < min && !noError) { 7713 state.raise("numbers out of order in {} quantifier"); 7714 } 7715 return true 7716 } 7717 } 7718 if (state.switchU && !noError) { 7719 state.raise("Incomplete quantifier"); 7720 } 7721 state.pos = start; 7722 } 7723 return false 7724 }; 7725 7726 // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom 7727 pp$1.regexp_eatAtom = function(state) { 7728 return ( 7729 this.regexp_eatPatternCharacters(state) || 7730 state.eat(0x2E /* . */) || 7731 this.regexp_eatReverseSolidusAtomEscape(state) || 7732 this.regexp_eatCharacterClass(state) || 7733 this.regexp_eatUncapturingGroup(state) || 7734 this.regexp_eatCapturingGroup(state) 7735 ) 7736 }; 7737 pp$1.regexp_eatReverseSolidusAtomEscape = function(state) { 7738 var start = state.pos; 7739 if (state.eat(0x5C /* \ */)) { 7740 if (this.regexp_eatAtomEscape(state)) { 7741 return true 7742 } 7743 state.pos = start; 7744 } 7745 return false 7746 }; 7747 pp$1.regexp_eatUncapturingGroup = function(state) { 7748 var start = state.pos; 7749 if (state.eat(0x28 /* ( */)) { 7750 if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { 7751 this.regexp_disjunction(state); 7752 if (state.eat(0x29 /* ) */)) { 7753 return true 7754 } 7755 state.raise("Unterminated group"); 7756 } 7757 state.pos = start; 7758 } 7759 return false 7760 }; 7761 pp$1.regexp_eatCapturingGroup = function(state) { 7762 if (state.eat(0x28 /* ( */)) { 7763 if (this.options.ecmaVersion >= 9) { 7764 this.regexp_groupSpecifier(state); 7765 } else if (state.current() === 0x3F /* ? */) { 7766 state.raise("Invalid group"); 7767 } 7768 this.regexp_disjunction(state); 7769 if (state.eat(0x29 /* ) */)) { 7770 state.numCapturingParens += 1; 7771 return true 7772 } 7773 state.raise("Unterminated group"); 7774 } 7775 return false 7776 }; 7777 7778 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom 7779 pp$1.regexp_eatExtendedAtom = function(state) { 7780 return ( 7781 state.eat(0x2E /* . */) || 7782 this.regexp_eatReverseSolidusAtomEscape(state) || 7783 this.regexp_eatCharacterClass(state) || 7784 this.regexp_eatUncapturingGroup(state) || 7785 this.regexp_eatCapturingGroup(state) || 7786 this.regexp_eatInvalidBracedQuantifier(state) || 7787 this.regexp_eatExtendedPatternCharacter(state) 7788 ) 7789 }; 7790 7791 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier 7792 pp$1.regexp_eatInvalidBracedQuantifier = function(state) { 7793 if (this.regexp_eatBracedQuantifier(state, true)) { 7794 state.raise("Nothing to repeat"); 7795 } 7796 return false 7797 }; 7798 7799 // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter 7800 pp$1.regexp_eatSyntaxCharacter = function(state) { 7801 var ch = state.current(); 7802 if (isSyntaxCharacter(ch)) { 7803 state.lastIntValue = ch; 7804 state.advance(); 7805 return true 7806 } 7807 return false 7808 }; 7809 function isSyntaxCharacter(ch) { 7810 return ( 7811 ch === 0x24 /* $ */ || 7812 ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || 7813 ch === 0x2E /* . */ || 7814 ch === 0x3F /* ? */ || 7815 ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || 7816 ch >= 0x7B /* { */ && ch <= 0x7D /* } */ 7817 ) 7818 } 7819 7820 // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter 7821 // But eat eager. 7822 pp$1.regexp_eatPatternCharacters = function(state) { 7823 var start = state.pos; 7824 var ch = 0; 7825 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { 7826 state.advance(); 7827 } 7828 return state.pos !== start 7829 }; 7830 7831 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter 7832 pp$1.regexp_eatExtendedPatternCharacter = function(state) { 7833 var ch = state.current(); 7834 if ( 7835 ch !== -1 && 7836 ch !== 0x24 /* $ */ && 7837 !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && 7838 ch !== 0x2E /* . */ && 7839 ch !== 0x3F /* ? */ && 7840 ch !== 0x5B /* [ */ && 7841 ch !== 0x5E /* ^ */ && 7842 ch !== 0x7C /* | */ 7843 ) { 7844 state.advance(); 7845 return true 7846 } 7847 return false 7848 }; 7849 7850 // GroupSpecifier :: 7851 // [empty] 7852 // `?` GroupName 7853 pp$1.regexp_groupSpecifier = function(state) { 7854 if (state.eat(0x3F /* ? */)) { 7855 if (this.regexp_eatGroupName(state)) { 7856 if (state.groupNames.indexOf(state.lastStringValue) !== -1) { 7857 state.raise("Duplicate capture group name"); 7858 } 7859 state.groupNames.push(state.lastStringValue); 7860 return 7861 } 7862 state.raise("Invalid group"); 7863 } 7864 }; 7865 7866 // GroupName :: 7867 // `<` RegExpIdentifierName `>` 7868 // Note: this updates `state.lastStringValue` property with the eaten name. 7869 pp$1.regexp_eatGroupName = function(state) { 7870 state.lastStringValue = ""; 7871 if (state.eat(0x3C /* < */)) { 7872 if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { 7873 return true 7874 } 7875 state.raise("Invalid capture group name"); 7876 } 7877 return false 7878 }; 7879 7880 // RegExpIdentifierName :: 7881 // RegExpIdentifierStart 7882 // RegExpIdentifierName RegExpIdentifierPart 7883 // Note: this updates `state.lastStringValue` property with the eaten name. 7884 pp$1.regexp_eatRegExpIdentifierName = function(state) { 7885 state.lastStringValue = ""; 7886 if (this.regexp_eatRegExpIdentifierStart(state)) { 7887 state.lastStringValue += codePointToString(state.lastIntValue); 7888 while (this.regexp_eatRegExpIdentifierPart(state)) { 7889 state.lastStringValue += codePointToString(state.lastIntValue); 7890 } 7891 return true 7892 } 7893 return false 7894 }; 7895 7896 // RegExpIdentifierStart :: 7897 // UnicodeIDStart 7898 // `$` 7899 // `_` 7900 // `\` RegExpUnicodeEscapeSequence[+U] 7901 pp$1.regexp_eatRegExpIdentifierStart = function(state) { 7902 var start = state.pos; 7903 var forceU = this.options.ecmaVersion >= 11; 7904 var ch = state.current(forceU); 7905 state.advance(forceU); 7906 7907 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { 7908 ch = state.lastIntValue; 7909 } 7910 if (isRegExpIdentifierStart(ch)) { 7911 state.lastIntValue = ch; 7912 return true 7913 } 7914 7915 state.pos = start; 7916 return false 7917 }; 7918 function isRegExpIdentifierStart(ch) { 7919 return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ 7920 } 7921 7922 // RegExpIdentifierPart :: 7923 // UnicodeIDContinue 7924 // `$` 7925 // `_` 7926 // `\` RegExpUnicodeEscapeSequence[+U] 7927 // <ZWNJ> 7928 // <ZWJ> 7929 pp$1.regexp_eatRegExpIdentifierPart = function(state) { 7930 var start = state.pos; 7931 var forceU = this.options.ecmaVersion >= 11; 7932 var ch = state.current(forceU); 7933 state.advance(forceU); 7934 7935 if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { 7936 ch = state.lastIntValue; 7937 } 7938 if (isRegExpIdentifierPart(ch)) { 7939 state.lastIntValue = ch; 7940 return true 7941 } 7942 7943 state.pos = start; 7944 return false 7945 }; 7946 function isRegExpIdentifierPart(ch) { 7947 return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ 7948 } 7949 7950 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape 7951 pp$1.regexp_eatAtomEscape = function(state) { 7952 if ( 7953 this.regexp_eatBackReference(state) || 7954 this.regexp_eatCharacterClassEscape(state) || 7955 this.regexp_eatCharacterEscape(state) || 7956 (state.switchN && this.regexp_eatKGroupName(state)) 7957 ) { 7958 return true 7959 } 7960 if (state.switchU) { 7961 // Make the same message as V8. 7962 if (state.current() === 0x63 /* c */) { 7963 state.raise("Invalid unicode escape"); 7964 } 7965 state.raise("Invalid escape"); 7966 } 7967 return false 7968 }; 7969 pp$1.regexp_eatBackReference = function(state) { 7970 var start = state.pos; 7971 if (this.regexp_eatDecimalEscape(state)) { 7972 var n = state.lastIntValue; 7973 if (state.switchU) { 7974 // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape 7975 if (n > state.maxBackReference) { 7976 state.maxBackReference = n; 7977 } 7978 return true 7979 } 7980 if (n <= state.numCapturingParens) { 7981 return true 7982 } 7983 state.pos = start; 7984 } 7985 return false 7986 }; 7987 pp$1.regexp_eatKGroupName = function(state) { 7988 if (state.eat(0x6B /* k */)) { 7989 if (this.regexp_eatGroupName(state)) { 7990 state.backReferenceNames.push(state.lastStringValue); 7991 return true 7992 } 7993 state.raise("Invalid named reference"); 7994 } 7995 return false 7996 }; 7997 7998 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape 7999 pp$1.regexp_eatCharacterEscape = function(state) { 8000 return ( 8001 this.regexp_eatControlEscape(state) || 8002 this.regexp_eatCControlLetter(state) || 8003 this.regexp_eatZero(state) || 8004 this.regexp_eatHexEscapeSequence(state) || 8005 this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || 8006 (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || 8007 this.regexp_eatIdentityEscape(state) 8008 ) 8009 }; 8010 pp$1.regexp_eatCControlLetter = function(state) { 8011 var start = state.pos; 8012 if (state.eat(0x63 /* c */)) { 8013 if (this.regexp_eatControlLetter(state)) { 8014 return true 8015 } 8016 state.pos = start; 8017 } 8018 return false 8019 }; 8020 pp$1.regexp_eatZero = function(state) { 8021 if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { 8022 state.lastIntValue = 0; 8023 state.advance(); 8024 return true 8025 } 8026 return false 8027 }; 8028 8029 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape 8030 pp$1.regexp_eatControlEscape = function(state) { 8031 var ch = state.current(); 8032 if (ch === 0x74 /* t */) { 8033 state.lastIntValue = 0x09; /* \t */ 8034 state.advance(); 8035 return true 8036 } 8037 if (ch === 0x6E /* n */) { 8038 state.lastIntValue = 0x0A; /* \n */ 8039 state.advance(); 8040 return true 8041 } 8042 if (ch === 0x76 /* v */) { 8043 state.lastIntValue = 0x0B; /* \v */ 8044 state.advance(); 8045 return true 8046 } 8047 if (ch === 0x66 /* f */) { 8048 state.lastIntValue = 0x0C; /* \f */ 8049 state.advance(); 8050 return true 8051 } 8052 if (ch === 0x72 /* r */) { 8053 state.lastIntValue = 0x0D; /* \r */ 8054 state.advance(); 8055 return true 8056 } 8057 return false 8058 }; 8059 8060 // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter 8061 pp$1.regexp_eatControlLetter = function(state) { 8062 var ch = state.current(); 8063 if (isControlLetter(ch)) { 8064 state.lastIntValue = ch % 0x20; 8065 state.advance(); 8066 return true 8067 } 8068 return false 8069 }; 8070 function isControlLetter(ch) { 8071 return ( 8072 (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || 8073 (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) 8074 ) 8075 } 8076 8077 // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence 8078 pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { 8079 if ( forceU === void 0 ) forceU = false; 8080 8081 var start = state.pos; 8082 var switchU = forceU || state.switchU; 8083 8084 if (state.eat(0x75 /* u */)) { 8085 if (this.regexp_eatFixedHexDigits(state, 4)) { 8086 var lead = state.lastIntValue; 8087 if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { 8088 var leadSurrogateEnd = state.pos; 8089 if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { 8090 var trail = state.lastIntValue; 8091 if (trail >= 0xDC00 && trail <= 0xDFFF) { 8092 state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; 8093 return true 8094 } 8095 } 8096 state.pos = leadSurrogateEnd; 8097 state.lastIntValue = lead; 8098 } 8099 return true 8100 } 8101 if ( 8102 switchU && 8103 state.eat(0x7B /* { */) && 8104 this.regexp_eatHexDigits(state) && 8105 state.eat(0x7D /* } */) && 8106 isValidUnicode(state.lastIntValue) 8107 ) { 8108 return true 8109 } 8110 if (switchU) { 8111 state.raise("Invalid unicode escape"); 8112 } 8113 state.pos = start; 8114 } 8115 8116 return false 8117 }; 8118 function isValidUnicode(ch) { 8119 return ch >= 0 && ch <= 0x10FFFF 8120 } 8121 8122 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape 8123 pp$1.regexp_eatIdentityEscape = function(state) { 8124 if (state.switchU) { 8125 if (this.regexp_eatSyntaxCharacter(state)) { 8126 return true 8127 } 8128 if (state.eat(0x2F /* / */)) { 8129 state.lastIntValue = 0x2F; /* / */ 8130 return true 8131 } 8132 return false 8133 } 8134 8135 var ch = state.current(); 8136 if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { 8137 state.lastIntValue = ch; 8138 state.advance(); 8139 return true 8140 } 8141 8142 return false 8143 }; 8144 8145 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape 8146 pp$1.regexp_eatDecimalEscape = function(state) { 8147 state.lastIntValue = 0; 8148 var ch = state.current(); 8149 if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { 8150 do { 8151 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); 8152 state.advance(); 8153 } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) 8154 return true 8155 } 8156 return false 8157 }; 8158 8159 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape 8160 pp$1.regexp_eatCharacterClassEscape = function(state) { 8161 var ch = state.current(); 8162 8163 if (isCharacterClassEscape(ch)) { 8164 state.lastIntValue = -1; 8165 state.advance(); 8166 return true 8167 } 8168 8169 if ( 8170 state.switchU && 8171 this.options.ecmaVersion >= 9 && 8172 (ch === 0x50 /* P */ || ch === 0x70 /* p */) 8173 ) { 8174 state.lastIntValue = -1; 8175 state.advance(); 8176 if ( 8177 state.eat(0x7B /* { */) && 8178 this.regexp_eatUnicodePropertyValueExpression(state) && 8179 state.eat(0x7D /* } */) 8180 ) { 8181 return true 8182 } 8183 state.raise("Invalid property name"); 8184 } 8185 8186 return false 8187 }; 8188 function isCharacterClassEscape(ch) { 8189 return ( 8190 ch === 0x64 /* d */ || 8191 ch === 0x44 /* D */ || 8192 ch === 0x73 /* s */ || 8193 ch === 0x53 /* S */ || 8194 ch === 0x77 /* w */ || 8195 ch === 0x57 /* W */ 8196 ) 8197 } 8198 8199 // UnicodePropertyValueExpression :: 8200 // UnicodePropertyName `=` UnicodePropertyValue 8201 // LoneUnicodePropertyNameOrValue 8202 pp$1.regexp_eatUnicodePropertyValueExpression = function(state) { 8203 var start = state.pos; 8204 8205 // UnicodePropertyName `=` UnicodePropertyValue 8206 if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { 8207 var name = state.lastStringValue; 8208 if (this.regexp_eatUnicodePropertyValue(state)) { 8209 var value = state.lastStringValue; 8210 this.regexp_validateUnicodePropertyNameAndValue(state, name, value); 8211 return true 8212 } 8213 } 8214 state.pos = start; 8215 8216 // LoneUnicodePropertyNameOrValue 8217 if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { 8218 var nameOrValue = state.lastStringValue; 8219 this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); 8220 return true 8221 } 8222 return false 8223 }; 8224 pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { 8225 if (!hasOwn(state.unicodeProperties.nonBinary, name)) 8226 { state.raise("Invalid property name"); } 8227 if (!state.unicodeProperties.nonBinary[name].test(value)) 8228 { state.raise("Invalid property value"); } 8229 }; 8230 pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { 8231 if (!state.unicodeProperties.binary.test(nameOrValue)) 8232 { state.raise("Invalid property name"); } 8233 }; 8234 8235 // UnicodePropertyName :: 8236 // UnicodePropertyNameCharacters 8237 pp$1.regexp_eatUnicodePropertyName = function(state) { 8238 var ch = 0; 8239 state.lastStringValue = ""; 8240 while (isUnicodePropertyNameCharacter(ch = state.current())) { 8241 state.lastStringValue += codePointToString(ch); 8242 state.advance(); 8243 } 8244 return state.lastStringValue !== "" 8245 }; 8246 function isUnicodePropertyNameCharacter(ch) { 8247 return isControlLetter(ch) || ch === 0x5F /* _ */ 8248 } 8249 8250 // UnicodePropertyValue :: 8251 // UnicodePropertyValueCharacters 8252 pp$1.regexp_eatUnicodePropertyValue = function(state) { 8253 var ch = 0; 8254 state.lastStringValue = ""; 8255 while (isUnicodePropertyValueCharacter(ch = state.current())) { 8256 state.lastStringValue += codePointToString(ch); 8257 state.advance(); 8258 } 8259 return state.lastStringValue !== "" 8260 }; 8261 function isUnicodePropertyValueCharacter(ch) { 8262 return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) 8263 } 8264 8265 // LoneUnicodePropertyNameOrValue :: 8266 // UnicodePropertyValueCharacters 8267 pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { 8268 return this.regexp_eatUnicodePropertyValue(state) 8269 }; 8270 8271 // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass 8272 pp$1.regexp_eatCharacterClass = function(state) { 8273 if (state.eat(0x5B /* [ */)) { 8274 state.eat(0x5E /* ^ */); 8275 this.regexp_classRanges(state); 8276 if (state.eat(0x5D /* ] */)) { 8277 return true 8278 } 8279 // Unreachable since it threw "unterminated regular expression" error before. 8280 state.raise("Unterminated character class"); 8281 } 8282 return false 8283 }; 8284 8285 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges 8286 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges 8287 // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash 8288 pp$1.regexp_classRanges = function(state) { 8289 while (this.regexp_eatClassAtom(state)) { 8290 var left = state.lastIntValue; 8291 if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { 8292 var right = state.lastIntValue; 8293 if (state.switchU && (left === -1 || right === -1)) { 8294 state.raise("Invalid character class"); 8295 } 8296 if (left !== -1 && right !== -1 && left > right) { 8297 state.raise("Range out of order in character class"); 8298 } 8299 } 8300 } 8301 }; 8302 8303 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom 8304 // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash 8305 pp$1.regexp_eatClassAtom = function(state) { 8306 var start = state.pos; 8307 8308 if (state.eat(0x5C /* \ */)) { 8309 if (this.regexp_eatClassEscape(state)) { 8310 return true 8311 } 8312 if (state.switchU) { 8313 // Make the same message as V8. 8314 var ch$1 = state.current(); 8315 if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { 8316 state.raise("Invalid class escape"); 8317 } 8318 state.raise("Invalid escape"); 8319 } 8320 state.pos = start; 8321 } 8322 8323 var ch = state.current(); 8324 if (ch !== 0x5D /* ] */) { 8325 state.lastIntValue = ch; 8326 state.advance(); 8327 return true 8328 } 8329 8330 return false 8331 }; 8332 8333 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape 8334 pp$1.regexp_eatClassEscape = function(state) { 8335 var start = state.pos; 8336 8337 if (state.eat(0x62 /* b */)) { 8338 state.lastIntValue = 0x08; /* <BS> */ 8339 return true 8340 } 8341 8342 if (state.switchU && state.eat(0x2D /* - */)) { 8343 state.lastIntValue = 0x2D; /* - */ 8344 return true 8345 } 8346 8347 if (!state.switchU && state.eat(0x63 /* c */)) { 8348 if (this.regexp_eatClassControlLetter(state)) { 8349 return true 8350 } 8351 state.pos = start; 8352 } 8353 8354 return ( 8355 this.regexp_eatCharacterClassEscape(state) || 8356 this.regexp_eatCharacterEscape(state) 8357 ) 8358 }; 8359 8360 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter 8361 pp$1.regexp_eatClassControlLetter = function(state) { 8362 var ch = state.current(); 8363 if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { 8364 state.lastIntValue = ch % 0x20; 8365 state.advance(); 8366 return true 8367 } 8368 return false 8369 }; 8370 8371 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence 8372 pp$1.regexp_eatHexEscapeSequence = function(state) { 8373 var start = state.pos; 8374 if (state.eat(0x78 /* x */)) { 8375 if (this.regexp_eatFixedHexDigits(state, 2)) { 8376 return true 8377 } 8378 if (state.switchU) { 8379 state.raise("Invalid escape"); 8380 } 8381 state.pos = start; 8382 } 8383 return false 8384 }; 8385 8386 // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits 8387 pp$1.regexp_eatDecimalDigits = function(state) { 8388 var start = state.pos; 8389 var ch = 0; 8390 state.lastIntValue = 0; 8391 while (isDecimalDigit(ch = state.current())) { 8392 state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); 8393 state.advance(); 8394 } 8395 return state.pos !== start 8396 }; 8397 function isDecimalDigit(ch) { 8398 return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ 8399 } 8400 8401 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits 8402 pp$1.regexp_eatHexDigits = function(state) { 8403 var start = state.pos; 8404 var ch = 0; 8405 state.lastIntValue = 0; 8406 while (isHexDigit(ch = state.current())) { 8407 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); 8408 state.advance(); 8409 } 8410 return state.pos !== start 8411 }; 8412 function isHexDigit(ch) { 8413 return ( 8414 (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || 8415 (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || 8416 (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) 8417 ) 8418 } 8419 function hexToInt(ch) { 8420 if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { 8421 return 10 + (ch - 0x41 /* A */) 8422 } 8423 if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { 8424 return 10 + (ch - 0x61 /* a */) 8425 } 8426 return ch - 0x30 /* 0 */ 8427 } 8428 8429 // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence 8430 // Allows only 0-377(octal) i.e. 0-255(decimal). 8431 pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) { 8432 if (this.regexp_eatOctalDigit(state)) { 8433 var n1 = state.lastIntValue; 8434 if (this.regexp_eatOctalDigit(state)) { 8435 var n2 = state.lastIntValue; 8436 if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { 8437 state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; 8438 } else { 8439 state.lastIntValue = n1 * 8 + n2; 8440 } 8441 } else { 8442 state.lastIntValue = n1; 8443 } 8444 return true 8445 } 8446 return false 8447 }; 8448 8449 // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit 8450 pp$1.regexp_eatOctalDigit = function(state) { 8451 var ch = state.current(); 8452 if (isOctalDigit(ch)) { 8453 state.lastIntValue = ch - 0x30; /* 0 */ 8454 state.advance(); 8455 return true 8456 } 8457 state.lastIntValue = 0; 8458 return false 8459 }; 8460 function isOctalDigit(ch) { 8461 return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ 8462 } 8463 8464 // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits 8465 // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit 8466 // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence 8467 pp$1.regexp_eatFixedHexDigits = function(state, length) { 8468 var start = state.pos; 8469 state.lastIntValue = 0; 8470 for (var i = 0; i < length; ++i) { 8471 var ch = state.current(); 8472 if (!isHexDigit(ch)) { 8473 state.pos = start; 8474 return false 8475 } 8476 state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); 8477 state.advance(); 8478 } 8479 return true 8480 }; 8481 8482 // Object type used to represent tokens. Note that normally, tokens 8483 // simply exist as properties on the parser object. This is only 8484 // used for the onToken callback and the external tokenizer. 8485 8486 var Token = function Token(p) { 8487 this.type = p.type; 8488 this.value = p.value; 8489 this.start = p.start; 8490 this.end = p.end; 8491 if (p.options.locations) 8492 { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } 8493 if (p.options.ranges) 8494 { this.range = [p.start, p.end]; } 8495 }; 8496 8497 // ## Tokenizer 8498 8499 var pp = Parser.prototype; 8500 8501 // Move to the next token 8502 8503 pp.next = function(ignoreEscapeSequenceInKeyword) { 8504 if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) 8505 { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } 8506 if (this.options.onToken) 8507 { this.options.onToken(new Token(this)); } 8508 8509 this.lastTokEnd = this.end; 8510 this.lastTokStart = this.start; 8511 this.lastTokEndLoc = this.endLoc; 8512 this.lastTokStartLoc = this.startLoc; 8513 this.nextToken(); 8514 }; 8515 8516 pp.getToken = function() { 8517 this.next(); 8518 return new Token(this) 8519 }; 8520 8521 // If we're in an ES6 environment, make parsers iterable 8522 if (typeof Symbol !== "undefined") 8523 { pp[Symbol.iterator] = function() { 8524 var this$1$1 = this; 8525 8526 return { 8527 next: function () { 8528 var token = this$1$1.getToken(); 8529 return { 8530 done: token.type === types$1.eof, 8531 value: token 8532 } 8533 } 8534 } 8535 }; } 8536 8537 // Toggle strict mode. Re-reads the next number or string to please 8538 // pedantic tests (`"use strict"; 010;` should fail). 8539 8540 // Read a single token, updating the parser object's token-related 8541 // properties. 8542 8543 pp.nextToken = function() { 8544 var curContext = this.curContext(); 8545 if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } 8546 8547 this.start = this.pos; 8548 if (this.options.locations) { this.startLoc = this.curPosition(); } 8549 if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) } 8550 8551 if (curContext.override) { return curContext.override(this) } 8552 else { this.readToken(this.fullCharCodeAtPos()); } 8553 }; 8554 8555 pp.readToken = function(code) { 8556 // Identifier or keyword. '\uXXXX' sequences are allowed in 8557 // identifiers, so '\' also dispatches to that. 8558 if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) 8559 { return this.readWord() } 8560 8561 return this.getTokenFromCode(code) 8562 }; 8563 8564 pp.fullCharCodeAtPos = function() { 8565 var code = this.input.charCodeAt(this.pos); 8566 if (code <= 0xd7ff || code >= 0xdc00) { return code } 8567 var next = this.input.charCodeAt(this.pos + 1); 8568 return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00 8569 }; 8570 8571 pp.skipBlockComment = function() { 8572 var startLoc = this.options.onComment && this.curPosition(); 8573 var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); 8574 if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } 8575 this.pos = end + 2; 8576 if (this.options.locations) { 8577 for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) { 8578 ++this.curLine; 8579 pos = this.lineStart = nextBreak; 8580 } 8581 } 8582 if (this.options.onComment) 8583 { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, 8584 startLoc, this.curPosition()); } 8585 }; 8586 8587 pp.skipLineComment = function(startSkip) { 8588 var start = this.pos; 8589 var startLoc = this.options.onComment && this.curPosition(); 8590 var ch = this.input.charCodeAt(this.pos += startSkip); 8591 while (this.pos < this.input.length && !isNewLine(ch)) { 8592 ch = this.input.charCodeAt(++this.pos); 8593 } 8594 if (this.options.onComment) 8595 { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, 8596 startLoc, this.curPosition()); } 8597 }; 8598 8599 // Called at the start of the parse and after every token. Skips 8600 // whitespace and comments, and. 8601 8602 pp.skipSpace = function() { 8603 loop: while (this.pos < this.input.length) { 8604 var ch = this.input.charCodeAt(this.pos); 8605 switch (ch) { 8606 case 32: case 160: // ' ' 8607 ++this.pos; 8608 break 8609 case 13: 8610 if (this.input.charCodeAt(this.pos + 1) === 10) { 8611 ++this.pos; 8612 } 8613 case 10: case 8232: case 8233: 8614 ++this.pos; 8615 if (this.options.locations) { 8616 ++this.curLine; 8617 this.lineStart = this.pos; 8618 } 8619 break 8620 case 47: // '/' 8621 switch (this.input.charCodeAt(this.pos + 1)) { 8622 case 42: // '*' 8623 this.skipBlockComment(); 8624 break 8625 case 47: 8626 this.skipLineComment(2); 8627 break 8628 default: 8629 break loop 8630 } 8631 break 8632 default: 8633 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { 8634 ++this.pos; 8635 } else { 8636 break loop 8637 } 8638 } 8639 } 8640 }; 8641 8642 // Called at the end of every token. Sets `end`, `val`, and 8643 // maintains `context` and `exprAllowed`, and skips the space after 8644 // the token, so that the next one's `start` will point at the 8645 // right position. 8646 8647 pp.finishToken = function(type, val) { 8648 this.end = this.pos; 8649 if (this.options.locations) { this.endLoc = this.curPosition(); } 8650 var prevType = this.type; 8651 this.type = type; 8652 this.value = val; 8653 8654 this.updateContext(prevType); 8655 }; 8656 8657 // ### Token reading 8658 8659 // This is the function that is called to fetch the next token. It 8660 // is somewhat obscure, because it works in character codes rather 8661 // than characters, and because operator parsing has been inlined 8662 // into it. 8663 // 8664 // All in the name of speed. 8665 // 8666 pp.readToken_dot = function() { 8667 var next = this.input.charCodeAt(this.pos + 1); 8668 if (next >= 48 && next <= 57) { return this.readNumber(true) } 8669 var next2 = this.input.charCodeAt(this.pos + 2); 8670 if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' 8671 this.pos += 3; 8672 return this.finishToken(types$1.ellipsis) 8673 } else { 8674 ++this.pos; 8675 return this.finishToken(types$1.dot) 8676 } 8677 }; 8678 8679 pp.readToken_slash = function() { // '/' 8680 var next = this.input.charCodeAt(this.pos + 1); 8681 if (this.exprAllowed) { ++this.pos; return this.readRegexp() } 8682 if (next === 61) { return this.finishOp(types$1.assign, 2) } 8683 return this.finishOp(types$1.slash, 1) 8684 }; 8685 8686 pp.readToken_mult_modulo_exp = function(code) { // '%*' 8687 var next = this.input.charCodeAt(this.pos + 1); 8688 var size = 1; 8689 var tokentype = code === 42 ? types$1.star : types$1.modulo; 8690 8691 // exponentiation operator ** and **= 8692 if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { 8693 ++size; 8694 tokentype = types$1.starstar; 8695 next = this.input.charCodeAt(this.pos + 2); 8696 } 8697 8698 if (next === 61) { return this.finishOp(types$1.assign, size + 1) } 8699 return this.finishOp(tokentype, size) 8700 }; 8701 8702 pp.readToken_pipe_amp = function(code) { // '|&' 8703 var next = this.input.charCodeAt(this.pos + 1); 8704 if (next === code) { 8705 if (this.options.ecmaVersion >= 12) { 8706 var next2 = this.input.charCodeAt(this.pos + 2); 8707 if (next2 === 61) { return this.finishOp(types$1.assign, 3) } 8708 } 8709 return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2) 8710 } 8711 if (next === 61) { return this.finishOp(types$1.assign, 2) } 8712 return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1) 8713 }; 8714 8715 pp.readToken_caret = function() { // '^' 8716 var next = this.input.charCodeAt(this.pos + 1); 8717 if (next === 61) { return this.finishOp(types$1.assign, 2) } 8718 return this.finishOp(types$1.bitwiseXOR, 1) 8719 }; 8720 8721 pp.readToken_plus_min = function(code) { // '+-' 8722 var next = this.input.charCodeAt(this.pos + 1); 8723 if (next === code) { 8724 if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && 8725 (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { 8726 // A `-->` line comment 8727 this.skipLineComment(3); 8728 this.skipSpace(); 8729 return this.nextToken() 8730 } 8731 return this.finishOp(types$1.incDec, 2) 8732 } 8733 if (next === 61) { return this.finishOp(types$1.assign, 2) } 8734 return this.finishOp(types$1.plusMin, 1) 8735 }; 8736 8737 pp.readToken_lt_gt = function(code) { // '<>' 8738 var next = this.input.charCodeAt(this.pos + 1); 8739 var size = 1; 8740 if (next === code) { 8741 size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; 8742 if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } 8743 return this.finishOp(types$1.bitShift, size) 8744 } 8745 if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && 8746 this.input.charCodeAt(this.pos + 3) === 45) { 8747 // `<!--`, an XML-style comment that should be interpreted as a line comment 8748 this.skipLineComment(4); 8749 this.skipSpace(); 8750 return this.nextToken() 8751 } 8752 if (next === 61) { size = 2; } 8753 return this.finishOp(types$1.relational, size) 8754 }; 8755 8756 pp.readToken_eq_excl = function(code) { // '=!' 8757 var next = this.input.charCodeAt(this.pos + 1); 8758 if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } 8759 if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' 8760 this.pos += 2; 8761 return this.finishToken(types$1.arrow) 8762 } 8763 return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1) 8764 }; 8765 8766 pp.readToken_question = function() { // '?' 8767 var ecmaVersion = this.options.ecmaVersion; 8768 if (ecmaVersion >= 11) { 8769 var next = this.input.charCodeAt(this.pos + 1); 8770 if (next === 46) { 8771 var next2 = this.input.charCodeAt(this.pos + 2); 8772 if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) } 8773 } 8774 if (next === 63) { 8775 if (ecmaVersion >= 12) { 8776 var next2$1 = this.input.charCodeAt(this.pos + 2); 8777 if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) } 8778 } 8779 return this.finishOp(types$1.coalesce, 2) 8780 } 8781 } 8782 return this.finishOp(types$1.question, 1) 8783 }; 8784 8785 pp.readToken_numberSign = function() { // '#' 8786 var ecmaVersion = this.options.ecmaVersion; 8787 var code = 35; // '#' 8788 if (ecmaVersion >= 13) { 8789 ++this.pos; 8790 code = this.fullCharCodeAtPos(); 8791 if (isIdentifierStart(code, true) || code === 92 /* '\' */) { 8792 return this.finishToken(types$1.privateId, this.readWord1()) 8793 } 8794 } 8795 8796 this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); 8797 }; 8798 8799 pp.getTokenFromCode = function(code) { 8800 switch (code) { 8801 // The interpretation of a dot depends on whether it is followed 8802 // by a digit or another two dots. 8803 case 46: // '.' 8804 return this.readToken_dot() 8805 8806 // Punctuation tokens. 8807 case 40: ++this.pos; return this.finishToken(types$1.parenL) 8808 case 41: ++this.pos; return this.finishToken(types$1.parenR) 8809 case 59: ++this.pos; return this.finishToken(types$1.semi) 8810 case 44: ++this.pos; return this.finishToken(types$1.comma) 8811 case 91: ++this.pos; return this.finishToken(types$1.bracketL) 8812 case 93: ++this.pos; return this.finishToken(types$1.bracketR) 8813 case 123: ++this.pos; return this.finishToken(types$1.braceL) 8814 case 125: ++this.pos; return this.finishToken(types$1.braceR) 8815 case 58: ++this.pos; return this.finishToken(types$1.colon) 8816 8817 case 96: // '`' 8818 if (this.options.ecmaVersion < 6) { break } 8819 ++this.pos; 8820 return this.finishToken(types$1.backQuote) 8821 8822 case 48: // '0' 8823 var next = this.input.charCodeAt(this.pos + 1); 8824 if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number 8825 if (this.options.ecmaVersion >= 6) { 8826 if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number 8827 if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number 8828 } 8829 8830 // Anything else beginning with a digit is an integer, octal 8831 // number, or float. 8832 case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 8833 return this.readNumber(false) 8834 8835 // Quotes produce strings. 8836 case 34: case 39: // '"', "'" 8837 return this.readString(code) 8838 8839 // Operators are parsed inline in tiny state machines. '=' (61) is 8840 // often referred to. `finishOp` simply skips the amount of 8841 // characters it is given as second argument, and returns a token 8842 // of the type given by its first argument. 8843 case 47: // '/' 8844 return this.readToken_slash() 8845 8846 case 37: case 42: // '%*' 8847 return this.readToken_mult_modulo_exp(code) 8848 8849 case 124: case 38: // '|&' 8850 return this.readToken_pipe_amp(code) 8851 8852 case 94: // '^' 8853 return this.readToken_caret() 8854 8855 case 43: case 45: // '+-' 8856 return this.readToken_plus_min(code) 8857 8858 case 60: case 62: // '<>' 8859 return this.readToken_lt_gt(code) 8860 8861 case 61: case 33: // '=!' 8862 return this.readToken_eq_excl(code) 8863 8864 case 63: // '?' 8865 return this.readToken_question() 8866 8867 case 126: // '~' 8868 return this.finishOp(types$1.prefix, 1) 8869 8870 case 35: // '#' 8871 return this.readToken_numberSign() 8872 } 8873 8874 this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); 8875 }; 8876 8877 pp.finishOp = function(type, size) { 8878 var str = this.input.slice(this.pos, this.pos + size); 8879 this.pos += size; 8880 return this.finishToken(type, str) 8881 }; 8882 8883 pp.readRegexp = function() { 8884 var escaped, inClass, start = this.pos; 8885 for (;;) { 8886 if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); } 8887 var ch = this.input.charAt(this.pos); 8888 if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } 8889 if (!escaped) { 8890 if (ch === "[") { inClass = true; } 8891 else if (ch === "]" && inClass) { inClass = false; } 8892 else if (ch === "/" && !inClass) { break } 8893 escaped = ch === "\\"; 8894 } else { escaped = false; } 8895 ++this.pos; 8896 } 8897 var pattern = this.input.slice(start, this.pos); 8898 ++this.pos; 8899 var flagsStart = this.pos; 8900 var flags = this.readWord1(); 8901 if (this.containsEsc) { this.unexpected(flagsStart); } 8902 8903 // Validate pattern 8904 var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); 8905 state.reset(start, pattern, flags); 8906 this.validateRegExpFlags(state); 8907 this.validateRegExpPattern(state); 8908 8909 // Create Literal#value property value. 8910 var value = null; 8911 try { 8912 value = new RegExp(pattern, flags); 8913 } catch (e) { 8914 // ESTree requires null if it failed to instantiate RegExp object. 8915 // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral 8916 } 8917 8918 return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value}) 8919 }; 8920 8921 // Read an integer in the given radix. Return null if zero digits 8922 // were read, the integer value otherwise. When `len` is given, this 8923 // will return `null` unless the integer has exactly `len` digits. 8924 8925 pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) { 8926 // `len` is used for character escape sequences. In that case, disallow separators. 8927 var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined; 8928 8929 // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b) 8930 // and isn't fraction part nor exponent part. In that case, if the first digit 8931 // is zero then disallow separators. 8932 var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48; 8933 8934 var start = this.pos, total = 0, lastCode = 0; 8935 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) { 8936 var code = this.input.charCodeAt(this.pos), val = (void 0); 8937 8938 if (allowSeparators && code === 95) { 8939 if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); } 8940 if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); } 8941 if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); } 8942 lastCode = code; 8943 continue 8944 } 8945 8946 if (code >= 97) { val = code - 97 + 10; } // a 8947 else if (code >= 65) { val = code - 65 + 10; } // A 8948 else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 8949 else { val = Infinity; } 8950 if (val >= radix) { break } 8951 lastCode = code; 8952 total = total * radix + val; 8953 } 8954 8955 if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); } 8956 if (this.pos === start || len != null && this.pos - start !== len) { return null } 8957 8958 return total 8959 }; 8960 8961 function stringToNumber(str, isLegacyOctalNumericLiteral) { 8962 if (isLegacyOctalNumericLiteral) { 8963 return parseInt(str, 8) 8964 } 8965 8966 // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value. 8967 return parseFloat(str.replace(/_/g, "")) 8968 } 8969 8970 function stringToBigInt(str) { 8971 if (typeof BigInt !== "function") { 8972 return null 8973 } 8974 8975 // `BigInt(value)` throws syntax error if the string contains numeric separators. 8976 return BigInt(str.replace(/_/g, "")) 8977 } 8978 8979 pp.readRadixNumber = function(radix) { 8980 var start = this.pos; 8981 this.pos += 2; // 0x 8982 var val = this.readInt(radix); 8983 if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } 8984 if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) { 8985 val = stringToBigInt(this.input.slice(start, this.pos)); 8986 ++this.pos; 8987 } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } 8988 return this.finishToken(types$1.num, val) 8989 }; 8990 8991 // Read an integer, octal integer, or floating-point number. 8992 8993 pp.readNumber = function(startsWithDot) { 8994 var start = this.pos; 8995 if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); } 8996 var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; 8997 if (octal && this.strict) { this.raise(start, "Invalid number"); } 8998 var next = this.input.charCodeAt(this.pos); 8999 if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) { 9000 var val$1 = stringToBigInt(this.input.slice(start, this.pos)); 9001 ++this.pos; 9002 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } 9003 return this.finishToken(types$1.num, val$1) 9004 } 9005 if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } 9006 if (next === 46 && !octal) { // '.' 9007 ++this.pos; 9008 this.readInt(10); 9009 next = this.input.charCodeAt(this.pos); 9010 } 9011 if ((next === 69 || next === 101) && !octal) { // 'eE' 9012 next = this.input.charCodeAt(++this.pos); 9013 if (next === 43 || next === 45) { ++this.pos; } // '+-' 9014 if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } 9015 } 9016 if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } 9017 9018 var val = stringToNumber(this.input.slice(start, this.pos), octal); 9019 return this.finishToken(types$1.num, val) 9020 }; 9021 9022 // Read a string value, interpreting backslash-escapes. 9023 9024 pp.readCodePoint = function() { 9025 var ch = this.input.charCodeAt(this.pos), code; 9026 9027 if (ch === 123) { // '{' 9028 if (this.options.ecmaVersion < 6) { this.unexpected(); } 9029 var codePos = ++this.pos; 9030 code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); 9031 ++this.pos; 9032 if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } 9033 } else { 9034 code = this.readHexChar(4); 9035 } 9036 return code 9037 }; 9038 9039 pp.readString = function(quote) { 9040 var out = "", chunkStart = ++this.pos; 9041 for (;;) { 9042 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); } 9043 var ch = this.input.charCodeAt(this.pos); 9044 if (ch === quote) { break } 9045 if (ch === 92) { // '\' 9046 out += this.input.slice(chunkStart, this.pos); 9047 out += this.readEscapedChar(false); 9048 chunkStart = this.pos; 9049 } else if (ch === 0x2028 || ch === 0x2029) { 9050 if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); } 9051 ++this.pos; 9052 if (this.options.locations) { 9053 this.curLine++; 9054 this.lineStart = this.pos; 9055 } 9056 } else { 9057 if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); } 9058 ++this.pos; 9059 } 9060 } 9061 out += this.input.slice(chunkStart, this.pos++); 9062 return this.finishToken(types$1.string, out) 9063 }; 9064 9065 // Reads template string tokens. 9066 9067 var INVALID_TEMPLATE_ESCAPE_ERROR = {}; 9068 9069 pp.tryReadTemplateToken = function() { 9070 this.inTemplateElement = true; 9071 try { 9072 this.readTmplToken(); 9073 } catch (err) { 9074 if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { 9075 this.readInvalidTemplateToken(); 9076 } else { 9077 throw err 9078 } 9079 } 9080 9081 this.inTemplateElement = false; 9082 }; 9083 9084 pp.invalidStringToken = function(position, message) { 9085 if (this.inTemplateElement && this.options.ecmaVersion >= 9) { 9086 throw INVALID_TEMPLATE_ESCAPE_ERROR 9087 } else { 9088 this.raise(position, message); 9089 } 9090 }; 9091 9092 pp.readTmplToken = function() { 9093 var out = "", chunkStart = this.pos; 9094 for (;;) { 9095 if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); } 9096 var ch = this.input.charCodeAt(this.pos); 9097 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' 9098 if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) { 9099 if (ch === 36) { 9100 this.pos += 2; 9101 return this.finishToken(types$1.dollarBraceL) 9102 } else { 9103 ++this.pos; 9104 return this.finishToken(types$1.backQuote) 9105 } 9106 } 9107 out += this.input.slice(chunkStart, this.pos); 9108 return this.finishToken(types$1.template, out) 9109 } 9110 if (ch === 92) { // '\' 9111 out += this.input.slice(chunkStart, this.pos); 9112 out += this.readEscapedChar(true); 9113 chunkStart = this.pos; 9114 } else if (isNewLine(ch)) { 9115 out += this.input.slice(chunkStart, this.pos); 9116 ++this.pos; 9117 switch (ch) { 9118 case 13: 9119 if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } 9120 case 10: 9121 out += "\n"; 9122 break 9123 default: 9124 out += String.fromCharCode(ch); 9125 break 9126 } 9127 if (this.options.locations) { 9128 ++this.curLine; 9129 this.lineStart = this.pos; 9130 } 9131 chunkStart = this.pos; 9132 } else { 9133 ++this.pos; 9134 } 9135 } 9136 }; 9137 9138 // Reads a template token to search for the end, without validating any escape sequences 9139 pp.readInvalidTemplateToken = function() { 9140 for (; this.pos < this.input.length; this.pos++) { 9141 switch (this.input[this.pos]) { 9142 case "\\": 9143 ++this.pos; 9144 break 9145 9146 case "$": 9147 if (this.input[this.pos + 1] !== "{") { 9148 break 9149 } 9150 9151 // falls through 9152 case "`": 9153 return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos)) 9154 9155 // no default 9156 } 9157 } 9158 this.raise(this.start, "Unterminated template"); 9159 }; 9160 9161 // Used to read escaped characters 9162 9163 pp.readEscapedChar = function(inTemplate) { 9164 var ch = this.input.charCodeAt(++this.pos); 9165 ++this.pos; 9166 switch (ch) { 9167 case 110: return "\n" // 'n' -> '\n' 9168 case 114: return "\r" // 'r' -> '\r' 9169 case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' 9170 case 117: return codePointToString(this.readCodePoint()) // 'u' 9171 case 116: return "\t" // 't' -> '\t' 9172 case 98: return "\b" // 'b' -> '\b' 9173 case 118: return "\u000b" // 'v' -> '\u000b' 9174 case 102: return "\f" // 'f' -> '\f' 9175 case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' 9176 case 10: // ' \n' 9177 if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } 9178 return "" 9179 case 56: 9180 case 57: 9181 if (this.strict) { 9182 this.invalidStringToken( 9183 this.pos - 1, 9184 "Invalid escape sequence" 9185 ); 9186 } 9187 if (inTemplate) { 9188 var codePos = this.pos - 1; 9189 9190 this.invalidStringToken( 9191 codePos, 9192 "Invalid escape sequence in template string" 9193 ); 9194 } 9195 default: 9196 if (ch >= 48 && ch <= 55) { 9197 var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; 9198 var octal = parseInt(octalStr, 8); 9199 if (octal > 255) { 9200 octalStr = octalStr.slice(0, -1); 9201 octal = parseInt(octalStr, 8); 9202 } 9203 this.pos += octalStr.length - 1; 9204 ch = this.input.charCodeAt(this.pos); 9205 if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { 9206 this.invalidStringToken( 9207 this.pos - 1 - octalStr.length, 9208 inTemplate 9209 ? "Octal literal in template string" 9210 : "Octal literal in strict mode" 9211 ); 9212 } 9213 return String.fromCharCode(octal) 9214 } 9215 if (isNewLine(ch)) { 9216 // Unicode new line characters after \ get removed from output in both 9217 // template literals and strings 9218 return "" 9219 } 9220 return String.fromCharCode(ch) 9221 } 9222 }; 9223 9224 // Used to read character escape sequences ('\x', '\u', '\U'). 9225 9226 pp.readHexChar = function(len) { 9227 var codePos = this.pos; 9228 var n = this.readInt(16, len); 9229 if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } 9230 return n 9231 }; 9232 9233 // Read an identifier, and return it as a string. Sets `this.containsEsc` 9234 // to whether the word contained a '\u' escape. 9235 // 9236 // Incrementally adds only escaped chars, adding other chunks as-is 9237 // as a micro-optimization. 9238 9239 pp.readWord1 = function() { 9240 this.containsEsc = false; 9241 var word = "", first = true, chunkStart = this.pos; 9242 var astral = this.options.ecmaVersion >= 6; 9243 while (this.pos < this.input.length) { 9244 var ch = this.fullCharCodeAtPos(); 9245 if (isIdentifierChar(ch, astral)) { 9246 this.pos += ch <= 0xffff ? 1 : 2; 9247 } else if (ch === 92) { // "\" 9248 this.containsEsc = true; 9249 word += this.input.slice(chunkStart, this.pos); 9250 var escStart = this.pos; 9251 if (this.input.charCodeAt(++this.pos) !== 117) // "u" 9252 { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); } 9253 ++this.pos; 9254 var esc = this.readCodePoint(); 9255 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) 9256 { this.invalidStringToken(escStart, "Invalid Unicode escape"); } 9257 word += codePointToString(esc); 9258 chunkStart = this.pos; 9259 } else { 9260 break 9261 } 9262 first = false; 9263 } 9264 return word + this.input.slice(chunkStart, this.pos) 9265 }; 9266 9267 // Read an identifier or keyword token. Will check for reserved 9268 // words when necessary. 9269 9270 pp.readWord = function() { 9271 var word = this.readWord1(); 9272 var type = types$1.name; 9273 if (this.keywords.test(word)) { 9274 type = keywords[word]; 9275 } 9276 return this.finishToken(type, word) 9277 }; 9278 9279 // Acorn is a tiny, fast JavaScript parser written in JavaScript. 9280 9281 var version = "8.8.2"; 9282 9283 Parser.acorn = { 9284 Parser: Parser, 9285 version: version, 9286 defaultOptions: defaultOptions, 9287 Position: Position, 9288 SourceLocation: SourceLocation, 9289 getLineInfo: getLineInfo, 9290 Node: Node, 9291 TokenType: TokenType, 9292 tokTypes: types$1, 9293 keywordTypes: keywords, 9294 TokContext: TokContext, 9295 tokContexts: types, 9296 isIdentifierChar: isIdentifierChar, 9297 isIdentifierStart: isIdentifierStart, 9298 Token: Token, 9299 isNewLine: isNewLine, 9300 lineBreak: lineBreak, 9301 lineBreakG: lineBreakG, 9302 nonASCIIwhitespace: nonASCIIwhitespace 9303 }; 9304 9305 // The main exported interface (under `self.acorn` when in the 9306 // browser) is a `parse` function that takes a code string and 9307 // returns an abstract syntax tree as specified by [Mozilla parser 9308 // API][api]. 9309 // 9310 // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API 9311 9312 function parse(input, options) { 9313 return Parser.parse(input, options) 9314 } 9315 9316 // This function tries to parse a single expression at a given 9317 // offset in a string. Useful for parsing mixed-language formats 9318 // that embed JavaScript expressions. 9319 9320 function parseExpressionAt(input, pos, options) { 9321 return Parser.parseExpressionAt(input, pos, options) 9322 } 9323 9324 // Acorn is organized as a tokenizer and a recursive-descent parser. 9325 // The `tokenizer` export provides an interface to the tokenizer. 9326 9327 function tokenizer(input, options) { 9328 return Parser.tokenizer(input, options) 9329 } 9330 9331 exports.Node = Node; 9332 exports.Parser = Parser; 9333 exports.Position = Position; 9334 exports.SourceLocation = SourceLocation; 9335 exports.TokContext = TokContext; 9336 exports.Token = Token; 9337 exports.TokenType = TokenType; 9338 exports.defaultOptions = defaultOptions; 9339 exports.getLineInfo = getLineInfo; 9340 exports.isIdentifierChar = isIdentifierChar; 9341 exports.isIdentifierStart = isIdentifierStart; 9342 exports.isNewLine = isNewLine; 9343 exports.keywordTypes = keywords; 9344 exports.lineBreak = lineBreak; 9345 exports.lineBreakG = lineBreakG; 9346 exports.nonASCIIwhitespace = nonASCIIwhitespace; 9347 exports.parse = parse; 9348 exports.parseExpressionAt = parseExpressionAt; 9349 exports.tokContexts = types; 9350 exports.tokTypes = types$1; 9351 exports.tokenizer = tokenizer; 9352 exports.version = version; 9353 9354 })); 9355 } (acorn$1, acorn$1.exports)); 9356 return acorn$1.exports; 9357 } 9358 9359 /* eslint-disable complexity */ 9360 9361 var acorn = requireAcorn(); 9362 var sourceMap = requireSourceMap(); 9363 const NEWLINE_CODE = 10; 9364 9365 function prettyFast(input, options) { 9366 return new PrettyFast(options).getPrettifiedCodeAndSourceMap(input); 9367 } 9368 9369 // If any of these tokens are seen before a "[" token, we know that "[" token 9370 // is the start of an array literal, rather than a property access. 9371 // 9372 // The only exception is "}", which would need to be disambiguated by 9373 // parsing. The majority of the time, an open bracket following a closing 9374 // curly is going to be an array literal, so we brush the complication under 9375 // the rug, and handle the ambiguity by always assuming that it will be an 9376 // array literal. 9377 const PRE_ARRAY_LITERAL_TOKENS = new Set([ 9378 "typeof", 9379 "void", 9380 "delete", 9381 "case", 9382 "do", 9383 "=", 9384 "in", 9385 "of", 9386 "...", 9387 "{", 9388 "*", 9389 "/", 9390 "%", 9391 "else", 9392 ";", 9393 "++", 9394 "--", 9395 "+", 9396 "-", 9397 "~", 9398 "!", 9399 ":", 9400 "?", 9401 ">>", 9402 ">>>", 9403 "<<", 9404 "||", 9405 "&&", 9406 "<", 9407 ">", 9408 "<=", 9409 ">=", 9410 "instanceof", 9411 "&", 9412 "^", 9413 "|", 9414 "==", 9415 "!=", 9416 "===", 9417 "!==", 9418 ",", 9419 "}", 9420 ]); 9421 9422 // If any of these tokens are seen before a "{" token, we know that "{" token 9423 // is the start of an object literal, rather than the start of a block. 9424 const PRE_OBJECT_LITERAL_TOKENS = new Set([ 9425 "typeof", 9426 "void", 9427 "delete", 9428 "=", 9429 "in", 9430 "of", 9431 "...", 9432 "*", 9433 "/", 9434 "%", 9435 "++", 9436 "--", 9437 "+", 9438 "-", 9439 "~", 9440 "!", 9441 ">>", 9442 ">>>", 9443 "<<", 9444 "<", 9445 ">", 9446 "<=", 9447 ">=", 9448 "instanceof", 9449 "&", 9450 "^", 9451 "|", 9452 "==", 9453 "!=", 9454 "===", 9455 "!==", 9456 ]); 9457 9458 class PrettyFast { 9459 /** 9460 * @param {object} options: Provides configurability of the pretty printing. 9461 * @param {string} options.url: The URL string of the ugly JS code. 9462 * @param {string} options.indent: The string to indent code by. 9463 * @param {SourceMapGenerator} options.sourceMapGenerator: An optional sourceMapGenerator 9464 * the mappings will be added to. 9465 * @param {boolean} options.prefixWithNewLine: When true, the pretty printed code will start 9466 * with a line break 9467 * @param {Integer} options.originalStartLine: The line the passed script starts at (1-based). 9468 * This is used for inline scripts where we need to account for the lines 9469 * before the script tag 9470 * @param {Integer} options.originalStartColumn: The column the passed script starts at (1-based). 9471 * This is used for inline scripts where we need to account for the position 9472 * of the script tag within the line. 9473 * @param {Integer} options.generatedStartLine: The line where the pretty printed script 9474 * will start at (1-based). This is used for pretty printing HTML file, 9475 * where we might have handle previous inline scripts that impact the 9476 * position of this script. 9477 */ 9478 constructor(options = {}) { 9479 // The level of indents deep we are. 9480 this.#indentLevel = 0; 9481 this.#indentChar = options.indent; 9482 9483 // We will handle mappings between ugly and pretty printed code in this SourceMapGenerator. 9484 this.#sourceMapGenerator = 9485 options.sourceMapGenerator || 9486 new sourceMap.SourceMapGenerator({ 9487 file: options.url, 9488 }); 9489 9490 this.#file = options.url; 9491 this.#hasOriginalStartLine = "originalStartLine" in options; 9492 this.#hasOriginalStartColumn = "originalStartColumn" in options; 9493 this.#hasGeneratedStartLine = "generatedStartLine" in options; 9494 this.#originalStartLine = options.originalStartLine; 9495 this.#originalStartColumn = options.originalStartColumn; 9496 this.#generatedStartLine = options.generatedStartLine; 9497 this.#prefixWithNewLine = options.prefixWithNewLine; 9498 } 9499 9500 /* options */ 9501 #indentChar; 9502 #indentLevel; 9503 #file; 9504 #hasOriginalStartLine; 9505 #hasOriginalStartColumn; 9506 #hasGeneratedStartLine; 9507 #originalStartLine; 9508 #originalStartColumn; 9509 #prefixWithNewLine; 9510 #generatedStartLine; 9511 #sourceMapGenerator; 9512 9513 /* internals */ 9514 9515 // Whether or not we added a newline on after we added the previous token. 9516 #addedNewline = false; 9517 // Whether or not we added a space after we added the previous token. 9518 #addedSpace = false; 9519 #currentCode = ""; 9520 #currentLine = 1; 9521 #currentColumn = 0; 9522 // The tokens parsed by acorn. 9523 #tokenQueue; 9524 // The index of the current token in this.#tokenQueue. 9525 #currentTokenIndex; 9526 // The previous token we added to the pretty printed code. 9527 #previousToken; 9528 // Stack of token types/keywords that can affect whether we want to add a 9529 // newline or a space. We can make that decision based on what token type is 9530 // on the top of the stack. For example, a comma in a parameter list should 9531 // be followed by a space, while a comma in an object literal should be 9532 // followed by a newline. 9533 // 9534 // Strings that go on the stack: 9535 // 9536 // - "{" 9537 // - "{\n" 9538 // - "(" 9539 // - "(\n" 9540 // - "[" 9541 // - "[\n" 9542 // - "do" 9543 // - "?" 9544 // - "switch" 9545 // - "case" 9546 // - "default" 9547 // 9548 // The difference between "[" and "[\n" (as well as "{" and "{\n", and "(" and "(\n") 9549 // is that "\n" is used when we are treating (curly) brackets/parens as line delimiters 9550 // and should increment and decrement the indent level when we find them. 9551 // "[" can represent either a property access (e.g. `x["hi"]`), or an empty array literal 9552 // "{" only represents an empty object literals 9553 // "(" can represent lots of different things (wrapping expression, if/loop condition, function call, …) 9554 #stack = []; 9555 9556 /** 9557 * @param {string} input: The ugly JS code we want to pretty print. 9558 * @returns {object} 9559 * An object with the following properties: 9560 * - code: The pretty printed code string. 9561 * - map: A SourceMapGenerator instance. 9562 */ 9563 getPrettifiedCodeAndSourceMap(input) { 9564 // Add the initial new line if needed 9565 if (this.#prefixWithNewLine) { 9566 this.#write("\n"); 9567 } 9568 9569 // Pass through acorn's tokenizer and append tokens and comments into a 9570 // single queue to process. For example, the source file: 9571 // 9572 // foo 9573 // // a 9574 // // b 9575 // bar 9576 // 9577 // After this process, tokenQueue has the following token stream: 9578 // 9579 // [ foo, '// a', '// b', bar] 9580 this.#tokenQueue = this.#getTokens(input); 9581 9582 for (let i = 0, len = this.#tokenQueue.length; i < len; i++) { 9583 this.#currentTokenIndex = i; 9584 const token = this.#tokenQueue[i]; 9585 const nextToken = this.#tokenQueue[i + 1]; 9586 this.#handleToken(token, nextToken); 9587 9588 // Acorn's tokenizer re-uses tokens, so we have to copy the previous token on 9589 // every iteration. We follow acorn's lead here, and reuse the previousToken 9590 // object the same way that acorn reuses the token object. This allows us 9591 // to avoid allocations and minimize GC pauses. 9592 if (!this.#previousToken) { 9593 this.#previousToken = { loc: { start: {}, end: {} } }; 9594 } 9595 this.#previousToken.start = token.start; 9596 this.#previousToken.end = token.end; 9597 this.#previousToken.loc.start.line = token.loc.start.line; 9598 this.#previousToken.loc.start.column = token.loc.start.column; 9599 this.#previousToken.loc.end.line = token.loc.end.line; 9600 this.#previousToken.loc.end.column = token.loc.end.column; 9601 this.#previousToken.type = token.type; 9602 this.#previousToken.value = token.value; 9603 } 9604 9605 return { code: this.#currentCode, map: this.#sourceMapGenerator }; 9606 } 9607 9608 /** 9609 * Write a pretty printed string to the prettified string and for tokens, add their 9610 * mapping to the SourceMapGenerator. 9611 * 9612 * @param String str 9613 * The string to be added to the result. 9614 * @param Number line 9615 * The line number the string came from in the ugly source. 9616 * @param Number column 9617 * The column number the string came from in the ugly source. 9618 * @param Boolean isToken 9619 * Set to true when writing tokens, so we can differentiate them from the 9620 * whitespace we add. 9621 */ 9622 #write(str, line, column, isToken) { 9623 this.#currentCode += str; 9624 if (isToken) { 9625 this.#sourceMapGenerator.addMapping({ 9626 source: this.#file, 9627 // We need to swap original and generated locations, as the prettified text should 9628 // be seen by the sourcemap service as the "original" one. 9629 generated: { 9630 // originalStartLine is 1-based, and here we just want to offset by a number of 9631 // lines, so we need to decrement it 9632 line: this.#hasOriginalStartLine 9633 ? line + (this.#originalStartLine - 1) 9634 : line, 9635 // We only need to adjust the column number if we're looking at the first line, to 9636 // account for the html text before the opening <script> tag. 9637 column: 9638 line == 1 && this.#hasOriginalStartColumn 9639 ? column + this.#originalStartColumn 9640 : column, 9641 }, 9642 original: { 9643 // generatedStartLine is 1-based, and here we just want to offset by a number of 9644 // lines, so we need to decrement it. 9645 line: this.#hasGeneratedStartLine 9646 ? this.#currentLine + (this.#generatedStartLine - 1) 9647 : this.#currentLine, 9648 column: this.#currentColumn, 9649 }, 9650 name: null, 9651 }); 9652 } 9653 9654 for (let idx = 0, length = str.length; idx < length; idx++) { 9655 if (str.charCodeAt(idx) === NEWLINE_CODE) { 9656 this.#currentLine++; 9657 this.#currentColumn = 0; 9658 } else { 9659 this.#currentColumn++; 9660 } 9661 } 9662 } 9663 9664 /** 9665 * Add the given token to the pretty printed results. 9666 * 9667 * @param Object token 9668 * The token to add. 9669 */ 9670 #writeToken(token) { 9671 if (token.type.label == "string") { 9672 this.#write( 9673 `'${stringSanitize(token.value)}'`, 9674 token.loc.start.line, 9675 token.loc.start.column, 9676 true 9677 ); 9678 } else if (token.type.label == "template") { 9679 // The backticks, '${', '}' and the template literal's string content are 9680 // all separate tokens. 9681 // 9682 // For example, `AAA${BBB}CCC` becomes the following token sequence, 9683 // where the first template's token.value being 'AAA' and the second 9684 // template's token.value being 'CCC'. 9685 // 9686 // * token.type.label == '`' 9687 // * token.type.label == 'template' 9688 // * token.type.label == '${' 9689 // * token.type.label == 'name' 9690 // * token.type.label == '}' 9691 // * token.type.label == 'template' 9692 // * token.type.label == '`' 9693 // 9694 // So, just sanitize the token.value without enclosing with backticks. 9695 this.#write( 9696 templateSanitize(token.value), 9697 token.loc.start.line, 9698 token.loc.start.column, 9699 true 9700 ); 9701 } else if (token.type.label == "regexp") { 9702 this.#write( 9703 String(token.value.value), 9704 token.loc.start.line, 9705 token.loc.start.column, 9706 true 9707 ); 9708 } else { 9709 let value; 9710 if (token.value != null) { 9711 value = token.value; 9712 if (token.type.label === "privateId") { 9713 value = `#${value}`; 9714 } 9715 } else { 9716 value = token.type.label; 9717 } 9718 this.#write( 9719 String(value), 9720 token.loc.start.line, 9721 token.loc.start.column, 9722 true 9723 ); 9724 } 9725 } 9726 9727 /** 9728 * Returns the tokens computed with acorn. 9729 * 9730 * @param String input 9731 * The JS code we want the tokens of. 9732 * @returns Array<Object> 9733 */ 9734 #getTokens(input) { 9735 const tokens = []; 9736 9737 const res = acorn.tokenizer(input, { 9738 locations: true, 9739 ecmaVersion: "latest", 9740 onComment(block, text, start, end, startLoc, endLoc) { 9741 tokens.push({ 9742 type: {}, 9743 comment: true, 9744 block, 9745 text, 9746 loc: { start: startLoc, end: endLoc }, 9747 }); 9748 }, 9749 }); 9750 9751 for (;;) { 9752 const token = res.getToken(); 9753 tokens.push(token); 9754 if (token.type.label == "eof") { 9755 break; 9756 } 9757 } 9758 9759 return tokens; 9760 } 9761 9762 /** 9763 * Add the required whitespace before this token, whether that is a single 9764 * space, newline, and/or the indent on fresh lines. 9765 * 9766 * @param Object token 9767 * The token we are currently handling. 9768 * @param {object | undefined} nextToken 9769 * The next token, might not exist if we're on the last token 9770 */ 9771 #handleToken(token, nextToken) { 9772 if (token.comment) { 9773 let commentIndentLevel = this.#indentLevel; 9774 if (this.#previousToken?.loc?.end?.line == token.loc.start.line) { 9775 commentIndentLevel = 0; 9776 this.#write(" "); 9777 } 9778 this.#addComment( 9779 commentIndentLevel, 9780 token.block, 9781 token.text, 9782 token.loc.start.line, 9783 nextToken 9784 ); 9785 return; 9786 } 9787 9788 // Shorthand for token.type.keyword, so we don't have to repeatedly access 9789 // properties. 9790 const ttk = token.type.keyword; 9791 9792 if (ttk && this.#previousToken?.type?.label == ".") { 9793 token.type = acorn.tokTypes.name; 9794 } 9795 9796 // Shorthand for token.type.label, so we don't have to repeatedly access 9797 // properties. 9798 const ttl = token.type.label; 9799 9800 if (ttl == "eof") { 9801 if (!this.#addedNewline) { 9802 this.#write("\n"); 9803 } 9804 return; 9805 } 9806 9807 if (belongsOnStack(token)) { 9808 let stackEntry; 9809 9810 if (isArrayLiteral(token, this.#previousToken)) { 9811 // Don't add new lines for empty array literals 9812 stackEntry = nextToken?.type?.label === "]" ? "[" : "[\n"; 9813 } else if (isObjectLiteral(token, this.#previousToken)) { 9814 // Don't add new lines for empty object literals 9815 stackEntry = nextToken?.type?.label === "}" ? "{" : "{\n"; 9816 } else if ( 9817 isRoundBracketStartingLongParenthesis( 9818 token, 9819 this.#tokenQueue, 9820 this.#currentTokenIndex 9821 ) 9822 ) { 9823 stackEntry = "(\n"; 9824 } else if (ttl == "{") { 9825 // We need to add a line break for "{" which are not empty object literals 9826 stackEntry = "{\n"; 9827 } else { 9828 stackEntry = ttl || ttk; 9829 } 9830 9831 this.#stack.push(stackEntry); 9832 } 9833 9834 this.#maybeDecrementIndent(token); 9835 this.#prependWhiteSpace(token); 9836 this.#writeToken(token); 9837 this.#addedSpace = false; 9838 9839 // If the next token is going to be a comment starting on the same line, 9840 // then no need to add a new line here 9841 if ( 9842 !nextToken || 9843 !nextToken.comment || 9844 token.loc.end.line != nextToken.loc.start.line 9845 ) { 9846 this.#maybeAppendNewline(token); 9847 } 9848 9849 this.#maybePopStack(token); 9850 this.#maybeIncrementIndent(token); 9851 } 9852 9853 /** 9854 * Returns true if the given token should cause us to pop the stack. 9855 */ 9856 #maybePopStack(token) { 9857 const ttl = token.type.label; 9858 const ttk = token.type.keyword; 9859 const top = this.#stack.at(-1); 9860 9861 if ( 9862 ttl == "]" || 9863 ttl == ")" || 9864 ttl == "}" || 9865 (ttl == ":" && (top == "case" || top == "default" || top == "?")) || 9866 (ttk == "while" && top == "do") 9867 ) { 9868 this.#stack.pop(); 9869 if (ttl == "}" && this.#stack.at(-1) == "switch") { 9870 this.#stack.pop(); 9871 } 9872 } 9873 } 9874 9875 #maybeIncrementIndent(token) { 9876 if ( 9877 // Don't increment indent for empty object literals 9878 (token.type.label == "{" && this.#stack.at(-1) === "{\n") || 9879 // Don't increment indent for empty array literals 9880 (token.type.label == "[" && this.#stack.at(-1) === "[\n") || 9881 token.type.keyword == "switch" || 9882 (token.type.label == "(" && this.#stack.at(-1) === "(\n") 9883 ) { 9884 this.#indentLevel++; 9885 } 9886 } 9887 9888 #shouldDecrementIndent(token) { 9889 const top = this.#stack.at(-1); 9890 const ttl = token.type.label; 9891 return ( 9892 (ttl == "}" && top == "{\n") || 9893 (ttl == "]" && top == "[\n") || 9894 (ttl == ")" && top == "(\n") 9895 ); 9896 } 9897 9898 #maybeDecrementIndent(token) { 9899 if (!this.#shouldDecrementIndent(token)) { 9900 return; 9901 } 9902 9903 const ttl = token.type.label; 9904 this.#indentLevel--; 9905 if (ttl == "}" && this.#stack.at(-2) == "switch") { 9906 this.#indentLevel--; 9907 } 9908 } 9909 9910 /** 9911 * Add a comment to the pretty printed code. 9912 * 9913 * @param Number indentLevel 9914 * The number of indents deep we are (might be different from this.#indentLevel). 9915 * @param Boolean block 9916 * True if the comment is a multiline block style comment. 9917 * @param String text 9918 * The text of the comment. 9919 * @param Number line 9920 * The line number to comment appeared on. 9921 * @param Object nextToken 9922 * The next token if any. 9923 */ 9924 #addComment(indentLevel, block, text, line, nextToken) { 9925 const indentString = this.#indentChar.repeat(indentLevel); 9926 const needNewLineAfter = 9927 !block || !(nextToken && nextToken.loc.start.line == line); 9928 9929 if (block) { 9930 const commentLinesText = text 9931 .split(new RegExp(`/\n${indentString}/`, "g")) 9932 .join(`\n${indentString}`); 9933 9934 this.#write( 9935 `${indentString}/*${commentLinesText}*/${needNewLineAfter ? "\n" : " "}` 9936 ); 9937 } else { 9938 this.#write(`${indentString}//${text}\n`); 9939 } 9940 9941 this.#addedNewline = needNewLineAfter; 9942 this.#addedSpace = !needNewLineAfter; 9943 } 9944 9945 /** 9946 * Add the required whitespace before this token, whether that is a single 9947 * space, newline, and/or the indent on fresh lines. 9948 * 9949 * @param Object token 9950 * The token we are about to add to the pretty printed code. 9951 */ 9952 #prependWhiteSpace(token) { 9953 const ttk = token.type.keyword; 9954 const ttl = token.type.label; 9955 let newlineAdded = this.#addedNewline; 9956 let spaceAdded = this.#addedSpace; 9957 const ltt = this.#previousToken?.type?.label; 9958 9959 // Handle whitespace and newlines after "}" here instead of in 9960 // `isLineDelimiter` because it is only a line delimiter some of the 9961 // time. For example, we don't want to put "else if" on a new line after 9962 // the first if's block. 9963 if (this.#previousToken && ltt == "}") { 9964 if ( 9965 (ttk == "while" && this.#stack.at(-1) == "do") || 9966 needsSpaceBeforeClosingCurlyBracket(ttk) 9967 ) { 9968 this.#write(" "); 9969 spaceAdded = true; 9970 } else if (needsLineBreakBeforeClosingCurlyBracket(ttl)) { 9971 this.#write("\n"); 9972 newlineAdded = true; 9973 } 9974 } 9975 9976 if ( 9977 (ttl == ":" && this.#stack.at(-1) == "?") || 9978 (ttl == "}" && this.#stack.at(-1) == "${") 9979 ) { 9980 this.#write(" "); 9981 spaceAdded = true; 9982 } 9983 9984 if (this.#previousToken && ltt != "}" && ltt != "." && ttk == "else") { 9985 this.#write(" "); 9986 spaceAdded = true; 9987 } 9988 9989 const ensureNewline = () => { 9990 if (!newlineAdded) { 9991 this.#write("\n"); 9992 newlineAdded = true; 9993 } 9994 }; 9995 9996 if (isASI(token, this.#previousToken)) { 9997 ensureNewline(); 9998 } 9999 10000 if (this.#shouldDecrementIndent(token)) { 10001 ensureNewline(); 10002 } 10003 10004 if (newlineAdded) { 10005 let indentLevel = this.#indentLevel; 10006 if (ttk == "case" || ttk == "default") { 10007 indentLevel--; 10008 } 10009 this.#write(this.#indentChar.repeat(indentLevel)); 10010 } else if (!spaceAdded && needsSpaceAfter(token, this.#previousToken)) { 10011 this.#write(" "); 10012 spaceAdded = true; 10013 } 10014 } 10015 10016 /** 10017 * Append the necessary whitespace to the result after we have added the given 10018 * token. 10019 * 10020 * @param Object token 10021 * The token that was just added to the result. 10022 */ 10023 #maybeAppendNewline(token) { 10024 if (!isLineDelimiter(token, this.#stack)) { 10025 this.#addedNewline = false; 10026 return; 10027 } 10028 10029 this.#write("\n"); 10030 this.#addedNewline = true; 10031 } 10032 } 10033 10034 /** 10035 * Determines if we think that the given token starts an array literal. 10036 * 10037 * @param Object token 10038 * The token we want to determine if it is an array literal. 10039 * @param Object previousToken 10040 * The previous token we added to the pretty printed results. 10041 * 10042 * @returns Boolean 10043 * True if we believe it is an array literal, false otherwise. 10044 */ 10045 function isArrayLiteral(token, previousToken) { 10046 if (token.type.label != "[") { 10047 return false; 10048 } 10049 if (!previousToken) { 10050 return true; 10051 } 10052 if (previousToken.type.isAssign) { 10053 return true; 10054 } 10055 10056 return PRE_ARRAY_LITERAL_TOKENS.has( 10057 previousToken.type.keyword || 10058 // Some tokens ('of', 'yield', …) have a `token.type.keyword` of 'name' and their 10059 // actual value in `token.value` 10060 (previousToken.type.label == "name" 10061 ? previousToken.value 10062 : previousToken.type.label) 10063 ); 10064 } 10065 10066 /** 10067 * Determines if we think that the given token starts an object literal. 10068 * 10069 * @param Object token 10070 * The token we want to determine if it is an object literal. 10071 * @param Object previousToken 10072 * The previous token we added to the pretty printed results. 10073 * 10074 * @returns Boolean 10075 * True if we believe it is an object literal, false otherwise. 10076 */ 10077 function isObjectLiteral(token, previousToken) { 10078 if (token.type.label != "{") { 10079 return false; 10080 } 10081 if (!previousToken) { 10082 return false; 10083 } 10084 if (previousToken.type.isAssign) { 10085 return true; 10086 } 10087 return PRE_OBJECT_LITERAL_TOKENS.has( 10088 previousToken.type.keyword || previousToken.type.label 10089 ); 10090 } 10091 10092 /** 10093 * Determines if we think that the given token starts a long parenthesis 10094 * 10095 * @param {object} token 10096 * The token we want to determine if it is the beginning of a long paren. 10097 * @param {Array<object>} tokenQueue 10098 * The whole list of tokens parsed by acorn 10099 * @param {Integer} currentTokenIndex 10100 * The index of `token` in `tokenQueue` 10101 * @returns 10102 */ 10103 function isRoundBracketStartingLongParenthesis( 10104 token, 10105 tokenQueue, 10106 currentTokenIndex 10107 ) { 10108 if (token.type.label !== "(") { 10109 return false; 10110 } 10111 10112 // If we're just wrapping an object, we'll have a new line right after 10113 if (tokenQueue[currentTokenIndex + 1].type.label == "{") { 10114 return false; 10115 } 10116 10117 // We're going to iterate through the following tokens until : 10118 // - we find the closing parent 10119 // - or we reached the maximum character we think should be in parenthesis 10120 const longParentContentLength = 60; 10121 10122 // Keep track of other parens so we know when we get the closing one for `token` 10123 let parenCount = 0; 10124 let parenContentLength = 0; 10125 for (let i = currentTokenIndex + 1, len = tokenQueue.length; i < len; i++) { 10126 const currToken = tokenQueue[i]; 10127 const ttl = currToken.type.label; 10128 10129 if (ttl == "(") { 10130 parenCount++; 10131 } else if (ttl == ")") { 10132 if (parenCount == 0) { 10133 // Matching closing paren, if we got here, we didn't reach the length limit, 10134 // as we return when parenContentLength is greater than the limit. 10135 return false; 10136 } 10137 parenCount--; 10138 } 10139 10140 // Aside block comments, all tokens start and end location are on the same line, so 10141 // we can use `start` and `end` to deduce the token length. 10142 const tokenLength = currToken.comment 10143 ? currToken.text.length 10144 : currToken.end - currToken.start; 10145 parenContentLength += tokenLength; 10146 10147 // If we didn't find the matching closing paren yet and the characters from the 10148 // tokens we evaluated so far are longer than the limit, so consider the token 10149 // a long paren. 10150 if (parenContentLength > longParentContentLength) { 10151 return true; 10152 } 10153 } 10154 10155 // if we get to here, we didn't found a closing paren, which shouldn't happen 10156 // (scripts with syntax error are not displayed in the debugger), but just to 10157 // be safe, return false. 10158 return false; 10159 } 10160 10161 // If any of these tokens are followed by a token on a new line, we know that 10162 // ASI cannot happen. 10163 const PREVENT_ASI_AFTER_TOKENS = new Set([ 10164 // Binary operators 10165 "*", 10166 "/", 10167 "%", 10168 "+", 10169 "-", 10170 "<<", 10171 ">>", 10172 ">>>", 10173 "<", 10174 ">", 10175 "<=", 10176 ">=", 10177 "instanceof", 10178 "in", 10179 "==", 10180 "!=", 10181 "===", 10182 "!==", 10183 "&", 10184 "^", 10185 "|", 10186 "&&", 10187 "||", 10188 ",", 10189 ".", 10190 "=", 10191 "*=", 10192 "/=", 10193 "%=", 10194 "+=", 10195 "-=", 10196 "<<=", 10197 ">>=", 10198 ">>>=", 10199 "&=", 10200 "^=", 10201 "|=", 10202 // Unary operators 10203 "delete", 10204 "void", 10205 "typeof", 10206 "~", 10207 "!", 10208 "new", 10209 // Function calls and grouped expressions 10210 "(", 10211 ]); 10212 10213 // If any of these tokens are on a line after the token before it, we know 10214 // that ASI cannot happen. 10215 const PREVENT_ASI_BEFORE_TOKENS = new Set([ 10216 // Binary operators 10217 "*", 10218 "/", 10219 "%", 10220 "<<", 10221 ">>", 10222 ">>>", 10223 "<", 10224 ">", 10225 "<=", 10226 ">=", 10227 "instanceof", 10228 "in", 10229 "==", 10230 "!=", 10231 "===", 10232 "!==", 10233 "&", 10234 "^", 10235 "|", 10236 "&&", 10237 "||", 10238 ",", 10239 ".", 10240 "=", 10241 "*=", 10242 "/=", 10243 "%=", 10244 "+=", 10245 "-=", 10246 "<<=", 10247 ">>=", 10248 ">>>=", 10249 "&=", 10250 "^=", 10251 "|=", 10252 // Function calls 10253 "(", 10254 ]); 10255 10256 /** 10257 * Determine if a token can look like an identifier. More precisely, 10258 * this determines if the token may end or start with a character from 10259 * [A-Za-z0-9_]. 10260 * 10261 * @param Object token 10262 * The token we are looking at. 10263 * 10264 * @returns Boolean 10265 * True if identifier-like. 10266 */ 10267 function isIdentifierLike(token) { 10268 const ttl = token.type.label; 10269 return ( 10270 ttl == "name" || ttl == "num" || ttl == "privateId" || !!token.type.keyword 10271 ); 10272 } 10273 10274 /** 10275 * Determines if Automatic Semicolon Insertion (ASI) occurs between these 10276 * tokens. 10277 * 10278 * @param Object token 10279 * The current token. 10280 * @param Object previousToken 10281 * The previous token we added to the pretty printed results. 10282 * 10283 * @returns Boolean 10284 * True if we believe ASI occurs. 10285 */ 10286 function isASI(token, previousToken) { 10287 if (!previousToken) { 10288 return false; 10289 } 10290 if (token.loc.start.line === previousToken.loc.start.line) { 10291 return false; 10292 } 10293 if ( 10294 previousToken.type.keyword == "return" || 10295 previousToken.type.keyword == "yield" || 10296 (previousToken.type.label == "name" && previousToken.value == "yield") 10297 ) { 10298 return true; 10299 } 10300 if ( 10301 PREVENT_ASI_AFTER_TOKENS.has( 10302 previousToken.type.label || previousToken.type.keyword 10303 ) 10304 ) { 10305 return false; 10306 } 10307 if (PREVENT_ASI_BEFORE_TOKENS.has(token.type.label || token.type.keyword)) { 10308 return false; 10309 } 10310 return true; 10311 } 10312 10313 /** 10314 * Determine if we should add a newline after the given token. 10315 * 10316 * @param Object token 10317 * The token we are looking at. 10318 * @param Array stack 10319 * The stack of open parens/curlies/brackets/etc. 10320 * 10321 * @returns Boolean 10322 * True if we should add a newline. 10323 */ 10324 function isLineDelimiter(token, stack) { 10325 const ttl = token.type.label; 10326 const top = stack.at(-1); 10327 return ( 10328 (ttl == ";" && top != "(") || 10329 // Don't add a new line for empty object literals 10330 (ttl == "{" && top == "{\n") || 10331 // Don't add a new line for empty array literals 10332 (ttl == "[" && top == "[\n") || 10333 ((ttl == "," || ttl == "||" || ttl == "&&") && top != "(") || 10334 (ttl == ":" && (top == "case" || top == "default")) || 10335 (ttl == "(" && top == "(\n") 10336 ); 10337 } 10338 10339 /** 10340 * Determines if we need to add a space after the token we are about to add. 10341 * 10342 * @param Object token 10343 * The token we are about to add to the pretty printed code. 10344 * @param Object [previousToken] 10345 * Optional previous token added to the pretty printed code. 10346 */ 10347 function needsSpaceAfter(token, previousToken) { 10348 if (previousToken && needsSpaceBetweenTokens(token, previousToken)) { 10349 return true; 10350 } 10351 10352 if (token.type.isAssign) { 10353 return true; 10354 } 10355 if (token.type.binop != null && previousToken) { 10356 return true; 10357 } 10358 if (token.type.label == "?") { 10359 return true; 10360 } 10361 if (token.type.label == "=>") { 10362 return true; 10363 } 10364 10365 return false; 10366 } 10367 10368 function needsSpaceBeforePreviousToken(previousToken) { 10369 if (previousToken.type.isLoop) { 10370 return true; 10371 } 10372 if (previousToken.type.isAssign) { 10373 return true; 10374 } 10375 if (previousToken.type.binop != null) { 10376 return true; 10377 } 10378 if (previousToken.value == "of") { 10379 return true; 10380 } 10381 10382 const previousTokenTypeLabel = previousToken.type.label; 10383 if (previousTokenTypeLabel == "?") { 10384 return true; 10385 } 10386 if (previousTokenTypeLabel == ":") { 10387 return true; 10388 } 10389 if (previousTokenTypeLabel == ",") { 10390 return true; 10391 } 10392 if (previousTokenTypeLabel == ";") { 10393 return true; 10394 } 10395 if (previousTokenTypeLabel == "${") { 10396 return true; 10397 } 10398 if (previousTokenTypeLabel == "=>") { 10399 return true; 10400 } 10401 return false; 10402 } 10403 10404 function isBreakContinueOrReturnStatement(previousTokenKeyword) { 10405 return ( 10406 previousTokenKeyword == "break" || 10407 previousTokenKeyword == "continue" || 10408 previousTokenKeyword == "return" 10409 ); 10410 } 10411 10412 function needsSpaceBeforePreviousTokenKeywordAfterNotDot(previousTokenKeyword) { 10413 return ( 10414 previousTokenKeyword != "debugger" && 10415 previousTokenKeyword != "null" && 10416 previousTokenKeyword != "true" && 10417 previousTokenKeyword != "false" && 10418 previousTokenKeyword != "this" && 10419 previousTokenKeyword != "default" 10420 ); 10421 } 10422 10423 function needsSpaceBeforeClosingParen(tokenTypeLabel) { 10424 return ( 10425 tokenTypeLabel != ")" && 10426 tokenTypeLabel != "]" && 10427 tokenTypeLabel != ";" && 10428 tokenTypeLabel != "," && 10429 tokenTypeLabel != "." 10430 ); 10431 } 10432 10433 /** 10434 * Determines if we need to add a space between the previous token we added and 10435 * the token we are about to add. 10436 * 10437 * @param Object token 10438 * The token we are about to add to the pretty printed code. 10439 * @param Object previousToken 10440 * The previous token added to the pretty printed code. 10441 */ 10442 function needsSpaceBetweenTokens(token, previousToken) { 10443 if (needsSpaceBeforePreviousToken(previousToken)) { 10444 return true; 10445 } 10446 10447 const ltt = previousToken.type.label; 10448 if (ltt == "num" && token.type.label == ".") { 10449 return true; 10450 } 10451 10452 const ltk = previousToken.type.keyword; 10453 const ttl = token.type.label; 10454 if (ltk != null && ttl != ".") { 10455 if (isBreakContinueOrReturnStatement(ltk)) { 10456 return ttl != ";"; 10457 } 10458 if (needsSpaceBeforePreviousTokenKeywordAfterNotDot(ltk)) { 10459 return true; 10460 } 10461 } 10462 10463 if (ltt == ")" && needsSpaceBeforeClosingParen(ttl)) { 10464 return true; 10465 } 10466 10467 if (isIdentifierLike(token) && isIdentifierLike(previousToken)) { 10468 // We must emit a space to avoid merging the tokens. 10469 return true; 10470 } 10471 10472 if (token.type.label == "{" && previousToken.type.label == "name") { 10473 return true; 10474 } 10475 10476 return false; 10477 } 10478 10479 function needsSpaceBeforeClosingCurlyBracket(tokenTypeKeyword) { 10480 return ( 10481 tokenTypeKeyword == "else" || 10482 tokenTypeKeyword == "catch" || 10483 tokenTypeKeyword == "finally" 10484 ); 10485 } 10486 10487 function needsLineBreakBeforeClosingCurlyBracket(tokenTypeLabel) { 10488 return ( 10489 tokenTypeLabel != "(" && 10490 tokenTypeLabel != ";" && 10491 tokenTypeLabel != "," && 10492 tokenTypeLabel != ")" && 10493 tokenTypeLabel != "." && 10494 tokenTypeLabel != "template" && 10495 tokenTypeLabel != "`" 10496 ); 10497 } 10498 10499 const commonEscapeCharacters = { 10500 // Backslash 10501 "\\": "\\\\", 10502 // Carriage return 10503 "\r": "\\r", 10504 // Tab 10505 "\t": "\\t", 10506 // Vertical tab 10507 "\v": "\\v", 10508 // Form feed 10509 "\f": "\\f", 10510 // Null character 10511 "\0": "\\x00", 10512 // Line separator 10513 "\u2028": "\\u2028", 10514 // Paragraph separator 10515 "\u2029": "\\u2029", 10516 }; 10517 10518 const stringEscapeCharacters = { 10519 ...commonEscapeCharacters, 10520 10521 // Newlines 10522 "\n": "\\n", 10523 // Single quotes 10524 "'": "\\'", 10525 }; 10526 10527 const templateEscapeCharacters = { 10528 ...commonEscapeCharacters, 10529 10530 // backtick 10531 "`": "\\`", 10532 }; 10533 10534 const stringRegExpString = `(${Object.values(stringEscapeCharacters).join( 10535 "|" 10536 )})`; 10537 const templateRegExpString = `(${Object.values(templateEscapeCharacters).join( 10538 "|" 10539 )})`; 10540 10541 const stringEscapeCharactersRegExp = new RegExp(stringRegExpString, "g"); 10542 const templateEscapeCharactersRegExp = new RegExp(templateRegExpString, "g"); 10543 10544 function stringSanitizerReplaceFunc(_, c) { 10545 return stringEscapeCharacters[c]; 10546 } 10547 function templateSanitizerReplaceFunc(_, c) { 10548 return templateEscapeCharacters[c]; 10549 } 10550 10551 /** 10552 * Make sure that we output the escaped character combination inside string 10553 * literals instead of various problematic characters. 10554 */ 10555 function stringSanitize(str) { 10556 return str.replace(stringEscapeCharactersRegExp, stringSanitizerReplaceFunc); 10557 } 10558 function templateSanitize(str) { 10559 return str.replace( 10560 templateEscapeCharactersRegExp, 10561 templateSanitizerReplaceFunc 10562 ); 10563 } 10564 10565 /** 10566 * Returns true if the given token type belongs on the stack. 10567 */ 10568 function belongsOnStack(token) { 10569 const ttl = token.type.label; 10570 const ttk = token.type.keyword; 10571 return ( 10572 ttl == "{" || 10573 ttl == "(" || 10574 ttl == "[" || 10575 ttl == "?" || 10576 ttl == "${" || 10577 ttk == "do" || 10578 ttk == "switch" || 10579 ttk == "case" || 10580 ttk == "default" 10581 ); 10582 } 10583 10584 var { SourceMapGenerator } = requireSourceMap(); 10585 10586 const sourceMapGeneratorByTaskId = new Map(); 10587 10588 function prettyPrint({ url, indent, sourceText }) { 10589 const { code, map: sourceMapGenerator } = prettyFast(sourceText, { 10590 url, 10591 indent, 10592 }); 10593 10594 return { 10595 code, 10596 sourceMap: sourceMapGenerator.toJSON(), 10597 }; 10598 } 10599 10600 function prettyPrintInlineScript({ 10601 taskId, 10602 url, 10603 indent, 10604 sourceText, 10605 originalStartLine, 10606 originalStartColumn, 10607 generatedStartLine, 10608 }) { 10609 let taskSourceMapGenerator; 10610 if (!sourceMapGeneratorByTaskId.has(taskId)) { 10611 taskSourceMapGenerator = new SourceMapGenerator({ file: url }); 10612 sourceMapGeneratorByTaskId.set(taskId, taskSourceMapGenerator); 10613 } else { 10614 taskSourceMapGenerator = sourceMapGeneratorByTaskId.get(taskId); 10615 } 10616 10617 const { code } = prettyFast(sourceText, { 10618 url, 10619 indent, 10620 sourceMapGenerator: taskSourceMapGenerator, 10621 /* 10622 * By default prettyPrint will trim the text, and we'd have the pretty text displayed 10623 * just after the script tag, e.g.: 10624 * 10625 * ``` 10626 * <script>if (true) { 10627 * something() 10628 * } 10629 * </script> 10630 * ``` 10631 * 10632 * We want the text to start on a new line, so prepend a line break, so we get 10633 * something like: 10634 * 10635 * ``` 10636 * <script> 10637 * if (true) { 10638 * something() 10639 * } 10640 * </script> 10641 * ``` 10642 */ 10643 prefixWithNewLine: true, 10644 originalStartLine, 10645 originalStartColumn, 10646 generatedStartLine, 10647 }); 10648 10649 // When a taskId was passed, we only return the pretty printed text. 10650 // The source map should be retrieved with getSourceMapForTask. 10651 return code; 10652 } 10653 10654 /** 10655 * Get the source map for a pretty-print task 10656 * 10657 * @param {Integer} taskId: The taskId that was used to call prettyPrint 10658 * @returns {object} A source map object 10659 */ 10660 function getSourceMapForTask(taskId) { 10661 if (!sourceMapGeneratorByTaskId.has(taskId)) { 10662 return null; 10663 } 10664 10665 const taskSourceMapGenerator = sourceMapGeneratorByTaskId.get(taskId); 10666 sourceMapGeneratorByTaskId.delete(taskId); 10667 return taskSourceMapGenerator.toJSON(); 10668 } 10669 10670 self.onmessage = workerUtilsExports.workerHandler({ 10671 prettyPrint, 10672 prettyPrintInlineScript, 10673 getSourceMapForTask, 10674 }); 10675 10676 }));