* @param {string} preferred_name * @returns {string}
(preferred_name)
| 708 | * @returns {string} |
| 709 | */ |
| 710 | generate(preferred_name) { |
| 711 | if (this.#porous) { |
| 712 | return /** @type {Scope} */ (this.parent).generate(preferred_name); |
| 713 | } |
| 714 | |
| 715 | preferred_name = preferred_name.replace(/[^a-zA-Z0-9_$]/g, '_').replace(/^[0-9]/, '_'); |
| 716 | |
| 717 | // Use cached counter to skip names already known to be taken (avoids O(n²) scanning) |
| 718 | let n = this.root.next_counter(preferred_name); |
| 719 | let name; |
| 720 | |
| 721 | if (n === 0) { |
| 722 | name = preferred_name; |
| 723 | n = 1; |
| 724 | } else { |
| 725 | name = `${preferred_name}_${n}`; |
| 726 | n++; |
| 727 | } |
| 728 | |
| 729 | while ( |
| 730 | this.references.has(name) || |
| 731 | this.declarations.has(name) || |
| 732 | this.root.conflicts.has(name) || |
| 733 | is_reserved(name) |
| 734 | ) { |
| 735 | name = `${preferred_name}_${n++}`; |
| 736 | } |
| 737 | |
| 738 | this.root.set_counter(preferred_name, n); |
| 739 | this.references.set(name, []); |
| 740 | this.root.conflicts.add(name); |
| 741 | return name; |
| 742 | } |
| 743 | |
| 744 | /** |
| 745 | * @param {string} name |
no test coverage detected