|
667 | 667 |
|
668 | 668 | // ## Parser utilities |
669 | 669 |
|
670 | | - var literal = /^(?:'((?:\\.|[^'\\])*?)'|"((?:\\.|[^"\\])*?)")/; |
| 670 | + var literal = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/; |
671 | 671 | pp$9.strictDirective = function(start) { |
672 | 672 | if (this.options.ecmaVersion < 5) { return false } |
673 | 673 | for (;;) { |
|
853 | 853 | // Statement) is allowed here. If context is not empty then only a Statement |
854 | 854 | // is allowed. However, `let [` is an explicit negative lookahead for |
855 | 855 | // ExpressionStatement, so special-case it first. |
856 | | - if (nextCh === 91 || nextCh === 92) { return true } // '[', '/' |
| 856 | + if (nextCh === 91 || nextCh === 92) { return true } // '[', '\' |
857 | 857 | if (context) { return false } |
858 | 858 |
|
859 | 859 | if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral |
|
1046 | 1046 | return this.parseFor(node, init$1) |
1047 | 1047 | } |
1048 | 1048 | var startsWithLet = this.isContextual("let"), isForOf = false; |
| 1049 | + var containsEsc = this.containsEsc; |
1049 | 1050 | var refDestructuringErrors = new DestructuringErrors; |
1050 | | - var init = this.parseExpression(awaitAt > -1 ? "await" : true, refDestructuringErrors); |
| 1051 | + var initPos = this.start; |
| 1052 | + var init = awaitAt > -1 |
| 1053 | + ? this.parseExprSubscripts(refDestructuringErrors, "await") |
| 1054 | + : this.parseExpression(true, refDestructuringErrors); |
1051 | 1055 | if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { |
1052 | | - if (this.options.ecmaVersion >= 9) { |
1053 | | - if (this.type === types$1._in) { |
1054 | | - if (awaitAt > -1) { this.unexpected(awaitAt); } |
1055 | | - } else { node.await = awaitAt > -1; } |
| 1056 | + if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt) |
| 1057 | + if (this.type === types$1._in) { this.unexpected(awaitAt); } |
| 1058 | + node.await = true; |
| 1059 | + } else if (isForOf && this.options.ecmaVersion >= 8) { |
| 1060 | + if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); } |
| 1061 | + else if (this.options.ecmaVersion >= 9) { node.await = false; } |
1056 | 1062 | } |
1057 | 1063 | if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } |
1058 | 1064 | this.toAssignable(init, false, refDestructuringErrors); |
|
2665 | 2671 | node.argument = this.parseMaybeUnary(null, true, update, forInit); |
2666 | 2672 | this.checkExpressionErrors(refDestructuringErrors, true); |
2667 | 2673 | if (update) { this.checkLValSimple(node.argument); } |
2668 | | - else if (this.strict && node.operator === "delete" && |
2669 | | - node.argument.type === "Identifier") |
| 2674 | + else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument)) |
2670 | 2675 | { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } |
2671 | 2676 | else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) |
2672 | 2677 | { this.raiseRecoverable(node.start, "Private fields can not be deleted"); } |
|
2701 | 2706 | } |
2702 | 2707 | }; |
2703 | 2708 |
|
| 2709 | + function isLocalVariableAccess(node) { |
| 2710 | + return ( |
| 2711 | + node.type === "Identifier" || |
| 2712 | + node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression) |
| 2713 | + ) |
| 2714 | + } |
| 2715 | + |
2704 | 2716 | function isPrivateFieldAccess(node) { |
2705 | 2717 | return ( |
2706 | 2718 | node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || |
2707 | | - node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) |
| 2719 | + node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) || |
| 2720 | + node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression) |
2708 | 2721 | ) |
2709 | 2722 | } |
2710 | 2723 |
|
|
3131 | 3144 | this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); |
3132 | 3145 | } |
3133 | 3146 | elem.value = { |
3134 | | - raw: this.value, |
| 3147 | + raw: this.value.replace(/\r\n?/g, "\n"), |
3135 | 3148 | cooked: null |
3136 | 3149 | }; |
3137 | 3150 | } else { |
|
3806 | 3819 |
|
3807 | 3820 | var pp$1 = Parser.prototype; |
3808 | 3821 |
|
| 3822 | + // Track disjunction structure to determine whether a duplicate |
| 3823 | + // capture group name is allowed because it is in a separate branch. |
| 3824 | + var BranchID = function BranchID(parent, base) { |
| 3825 | + // Parent disjunction branch |
| 3826 | + this.parent = parent; |
| 3827 | + // Identifies this set of sibling branches |
| 3828 | + this.base = base || this; |
| 3829 | + }; |
| 3830 | + |
| 3831 | + BranchID.prototype.separatedFrom = function separatedFrom (alt) { |
| 3832 | + // A branch is separate from another branch if they or any of |
| 3833 | + // their parents are siblings in a given disjunction |
| 3834 | + for (var self = this; self; self = self.parent) { |
| 3835 | + for (var other = alt; other; other = other.parent) { |
| 3836 | + if (self.base === other.base && self !== other) { return true } |
| 3837 | + } |
| 3838 | + } |
| 3839 | + return false |
| 3840 | + }; |
| 3841 | + |
| 3842 | + BranchID.prototype.sibling = function sibling () { |
| 3843 | + return new BranchID(this.parent, this.base) |
| 3844 | + }; |
| 3845 | + |
3809 | 3846 | var RegExpValidationState = function RegExpValidationState(parser) { |
3810 | 3847 | this.parser = parser; |
3811 | 3848 | this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : ""); |
|
3822 | 3859 | this.lastAssertionIsQuantifiable = false; |
3823 | 3860 | this.numCapturingParens = 0; |
3824 | 3861 | this.maxBackReference = 0; |
3825 | | - this.groupNames = []; |
| 3862 | + this.groupNames = Object.create(null); |
3826 | 3863 | this.backReferenceNames = []; |
| 3864 | + this.branchID = null; |
3827 | 3865 | }; |
3828 | 3866 |
|
3829 | 3867 | RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { |
|
3955 | 3993 | } |
3956 | 3994 | }; |
3957 | 3995 |
|
| 3996 | + function hasProp(obj) { |
| 3997 | + for (var _ in obj) { return true } |
| 3998 | + return false |
| 3999 | + } |
| 4000 | + |
3958 | 4001 | /** |
3959 | 4002 | * Validate the pattern part of a given RegExpLiteral. |
3960 | 4003 | * |
|
3969 | 4012 | // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* |
3970 | 4013 | // exception if _P_ did not conform to the grammar, if any elements of _P_ |
3971 | 4014 | // were not matched by the parse, or if any Early Error conditions exist. |
3972 | | - if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { |
| 4015 | + if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) { |
3973 | 4016 | state.switchN = true; |
3974 | 4017 | this.regexp_pattern(state); |
3975 | 4018 | } |
|
3983 | 4026 | state.lastAssertionIsQuantifiable = false; |
3984 | 4027 | state.numCapturingParens = 0; |
3985 | 4028 | state.maxBackReference = 0; |
3986 | | - state.groupNames.length = 0; |
| 4029 | + state.groupNames = Object.create(null); |
3987 | 4030 | state.backReferenceNames.length = 0; |
| 4031 | + state.branchID = null; |
3988 | 4032 |
|
3989 | 4033 | this.regexp_disjunction(state); |
3990 | 4034 |
|
|
4003 | 4047 | for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { |
4004 | 4048 | var name = list[i]; |
4005 | 4049 |
|
4006 | | - if (state.groupNames.indexOf(name) === -1) { |
| 4050 | + if (!state.groupNames[name]) { |
4007 | 4051 | state.raise("Invalid named capture referenced"); |
4008 | 4052 | } |
4009 | 4053 | } |
4010 | 4054 | }; |
4011 | 4055 |
|
4012 | 4056 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction |
4013 | 4057 | pp$1.regexp_disjunction = function(state) { |
| 4058 | + var trackDisjunction = this.options.ecmaVersion >= 16; |
| 4059 | + if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); } |
4014 | 4060 | this.regexp_alternative(state); |
4015 | 4061 | while (state.eat(0x7C /* | */)) { |
| 4062 | + if (trackDisjunction) { state.branchID = state.branchID.sibling(); } |
4016 | 4063 | this.regexp_alternative(state); |
4017 | 4064 | } |
| 4065 | + if (trackDisjunction) { state.branchID = state.branchID.parent; } |
4018 | 4066 |
|
4019 | 4067 | // Make the same message as V8. |
4020 | 4068 | if (this.regexp_eatQuantifier(state, true)) { |
|
4027 | 4075 |
|
4028 | 4076 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative |
4029 | 4077 | pp$1.regexp_alternative = function(state) { |
4030 | | - while (state.pos < state.source.length && this.regexp_eatTerm(state)) |
4031 | | - { } |
| 4078 | + while (state.pos < state.source.length && this.regexp_eatTerm(state)) {} |
4032 | 4079 | }; |
4033 | 4080 |
|
4034 | 4081 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term |
|
4266 | 4313 | // `?` GroupName |
4267 | 4314 | pp$1.regexp_groupSpecifier = function(state) { |
4268 | 4315 | if (state.eat(0x3F /* ? */)) { |
4269 | | - if (this.regexp_eatGroupName(state)) { |
4270 | | - if (state.groupNames.indexOf(state.lastStringValue) !== -1) { |
| 4316 | + if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); } |
| 4317 | + var trackDisjunction = this.options.ecmaVersion >= 16; |
| 4318 | + var known = state.groupNames[state.lastStringValue]; |
| 4319 | + if (known) { |
| 4320 | + if (trackDisjunction) { |
| 4321 | + for (var i = 0, list = known; i < list.length; i += 1) { |
| 4322 | + var altID = list[i]; |
| 4323 | + |
| 4324 | + if (!altID.separatedFrom(state.branchID)) |
| 4325 | + { state.raise("Duplicate capture group name"); } |
| 4326 | + } |
| 4327 | + } else { |
4271 | 4328 | state.raise("Duplicate capture group name"); |
4272 | 4329 | } |
4273 | | - state.groupNames.push(state.lastStringValue); |
4274 | | - return |
4275 | 4330 | } |
4276 | | - state.raise("Invalid group"); |
| 4331 | + if (trackDisjunction) { |
| 4332 | + (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID); |
| 4333 | + } else { |
| 4334 | + state.groupNames[state.lastStringValue] = true; |
| 4335 | + } |
4277 | 4336 | } |
4278 | 4337 | }; |
4279 | 4338 |
|
|
5778 | 5837 | break |
5779 | 5838 |
|
5780 | 5839 | case "$": |
5781 | | - if (this.input[this.pos + 1] !== "{") { |
5782 | | - break |
5783 | | - } |
5784 | | - |
5785 | | - // falls through |
| 5840 | + if (this.input[this.pos + 1] !== "{") { break } |
| 5841 | + // fall through |
5786 | 5842 | case "`": |
5787 | 5843 | return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos)) |
5788 | 5844 |
|
5789 | | - // no default |
| 5845 | + case "\r": |
| 5846 | + if (this.input[this.pos + 1] === "\n") { ++this.pos; } |
| 5847 | + // fall through |
| 5848 | + case "\n": case "\u2028": case "\u2029": |
| 5849 | + ++this.curLine; |
| 5850 | + this.lineStart = this.pos + 1; |
| 5851 | + break |
5790 | 5852 | } |
5791 | 5853 | } |
5792 | 5854 | this.raise(this.start, "Unterminated template"); |
|
5849 | 5911 | if (isNewLine(ch)) { |
5850 | 5912 | // Unicode new line characters after \ get removed from output in both |
5851 | 5913 | // template literals and strings |
| 5914 | + if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } |
5852 | 5915 | return "" |
5853 | 5916 | } |
5854 | 5917 | return String.fromCharCode(ch) |
|
5927 | 5990 | // [walk]: util/walk.js |
5928 | 5991 |
|
5929 | 5992 |
|
5930 | | - var version = "8.11.3"; |
| 5993 | + var version = "8.12.1"; |
5931 | 5994 |
|
5932 | 5995 | Parser.acorn = { |
5933 | 5996 | Parser: Parser, |
|
0 commit comments