diff --git a/src/public/libraries/eslint.js b/src/public/libraries/eslint.js index 6531ed30b..e596b0a7d 100644 --- a/src/public/libraries/eslint.js +++ b/src/public/libraries/eslint.js @@ -7572,544 +7572,593 @@ module.exports = _dereq_(23); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}]},{},[1]); -require=(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o...', true, true); +var tc_oTag = new TokContext('...', true, true); - tt.jsxName = new acorn.TokenType('jsxName'); - tt.jsxText = new acorn.TokenType('jsxText', {beforeExpr: true}); - tt.jsxTagStart = new acorn.TokenType('jsxTagStart'); - tt.jsxTagEnd = new acorn.TokenType('jsxTagEnd'); +var tok = { + jsxName: new TokenType('jsxName'), + jsxText: new TokenType('jsxText', { beforeExpr: true }), + jsxTagStart: new TokenType('jsxTagStart'), + jsxTagEnd: new TokenType('jsxTagEnd') +}; - tt.jsxTagStart.updateContext = function() { - this.context.push(tc.j_expr); // treat as beginning of JSX expression - this.context.push(tc.j_oTag); // start opening tag context - this.exprAllowed = false; - }; - tt.jsxTagEnd.updateContext = function(prevType) { - var out = this.context.pop(); - if (out === tc.j_oTag && prevType === tt.slash || out === tc.j_cTag) { - this.context.pop(); - this.exprAllowed = this.curContext() === tc.j_expr; - } else { - this.exprAllowed = true; - } - }; - - var pp = acorn.Parser.prototype; - - // Reads inline JSX contents token. - - pp.jsx_readToken = function() { - var out = '', chunkStart = this.pos; - for (;;) { - if (this.pos >= this.input.length) - this.raise(this.start, 'Unterminated JSX contents'); - var ch = this.input.charCodeAt(this.pos); - - switch (ch) { - case 60: // '<' - case 123: // '{' - if (this.pos === this.start) { - if (ch === 60 && this.exprAllowed) { - ++this.pos; - return this.finishToken(tt.jsxTagStart); - } - return this.getTokenFromCode(ch); - } - out += this.input.slice(chunkStart, this.pos); - return this.finishToken(tt.jsxText, out); - - case 38: // '&' - out += this.input.slice(chunkStart, this.pos); - out += this.jsx_readEntity(); - chunkStart = this.pos; - break; - - default: - if (acorn.isNewLine(ch)) { - out += this.input.slice(chunkStart, this.pos); - out += this.jsx_readNewLine(true); - chunkStart = this.pos; - } else { - ++this.pos; - } - } - } - }; - - pp.jsx_readNewLine = function(normalizeCRLF) { - var ch = this.input.charCodeAt(this.pos); - var out; - ++this.pos; - if (ch === 13 && this.input.charCodeAt(this.pos) === 10) { - ++this.pos; - out = normalizeCRLF ? '\n' : '\r\n'; - } else { - out = String.fromCharCode(ch); - } - if (this.options.locations) { - ++this.curLine; - this.lineStart = this.pos; - } - - return out; - }; - - pp.jsx_readString = function(quote) { - var out = '', chunkStart = ++this.pos; - for (;;) { - if (this.pos >= this.input.length) - this.raise(this.start, 'Unterminated string constant'); - var ch = this.input.charCodeAt(this.pos); - if (ch === quote) break; - if (ch === 38) { // '&' - out += this.input.slice(chunkStart, this.pos); - out += this.jsx_readEntity(); - chunkStart = this.pos; - } else if (acorn.isNewLine(ch)) { - out += this.input.slice(chunkStart, this.pos); - out += this.jsx_readNewLine(false); - chunkStart = this.pos; - } else { - ++this.pos; - } - } - out += this.input.slice(chunkStart, this.pos++); - return this.finishToken(tt.string, out); - }; - - pp.jsx_readEntity = function() { - var str = '', count = 0, entity; - var ch = this.input[this.pos]; - if (ch !== '&') - this.raise(this.pos, 'Entity must start with an ampersand'); - var startPos = ++this.pos; - while (this.pos < this.input.length && count++ < 10) { - ch = this.input[this.pos++]; - if (ch === ';') { - if (str[0] === '#') { - if (str[1] === 'x') { - str = str.substr(2); - if (hexNumber.test(str)) - entity = String.fromCharCode(parseInt(str, 16)); - } else { - str = str.substr(1); - if (decimalNumber.test(str)) - entity = String.fromCharCode(parseInt(str, 10)); - } - } else { - entity = XHTMLEntities[str]; - } - break; - } - str += ch; - } - if (!entity) { - this.pos = startPos; - return '&'; - } - return entity; - }; - - - // Read a JSX identifier (valid tag or attribute name). - // - // Optimized version since JSX identifiers can't contain - // escape characters and so can be read as single slice. - // Also assumes that first character was already checked - // by isIdentifierStart in readToken. - - pp.jsx_readWord = function() { - var ch, start = this.pos; - do { - ch = this.input.charCodeAt(++this.pos); - } while (acorn.isIdentifierChar(ch) || ch === 45); // '-' - return this.finishToken(tt.jsxName, this.input.slice(start, this.pos)); - }; - - // Transforms JSX element name to string. - - function getQualifiedJSXName(object) { - if (object.type === 'JSXIdentifier') - return object.name; - - if (object.type === 'JSXNamespacedName') - return object.namespace.name + ':' + object.name.name; - - if (object.type === 'JSXMemberExpression') - return getQualifiedJSXName(object.object) + '.' + - getQualifiedJSXName(object.property); +tok.jsxTagStart.updateContext = function () { + this.context.push(tc_expr); // treat as beginning of JSX expression + this.context.push(tc_oTag); // start opening tag context + this.exprAllowed = false; +}; +tok.jsxTagEnd.updateContext = function (prevType) { + var out = this.context.pop(); + if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) { + this.context.pop(); + this.exprAllowed = this.curContext() === tc_expr; + } else { + this.exprAllowed = true; } +}; - // Parse next token as JSX identifier +// Transforms JSX element name to string. - pp.jsx_parseIdentifier = function() { - var node = this.startNode(); - if (this.type === tt.jsxName) - node.name = this.value; - else if (this.type.keyword) - node.name = this.type.keyword; - else - this.unexpected(); - this.next(); - return this.finishNode(node, 'JSXIdentifier'); +function getQualifiedJSXName(object) { + if (!object) return object; + + if (object.type === 'JSXIdentifier') return object.name; + + if (object.type === 'JSXNamespacedName') return object.namespace.name + ':' + object.name.name; + + if (object.type === 'JSXMemberExpression') return getQualifiedJSXName(object.object) + '.' + getQualifiedJSXName(object.property); +} + +module.exports = function (options) { + options = options || {}; + return function (Parser) { + return plugin({ + allowNamespaces: options.allowNamespaces !== false, + allowNamespacedObjects: !!options.allowNamespacedObjects + }, Parser); }; +}; +module.exports.tokTypes = tok; - // Parse namespaced identifier. +function plugin(options, Parser) { + return function (_Parser) { + _inherits(_class, _Parser); - pp.jsx_parseNamespacedName = function() { - var startPos = this.start, startLoc = this.startLoc; - var name = this.jsx_parseIdentifier(); - if (!this.options.plugins.jsx.allowNamespaces || !this.eat(tt.colon)) return name; - var node = this.startNodeAt(startPos, startLoc); - node.namespace = name; - node.name = this.jsx_parseIdentifier(); - return this.finishNode(node, 'JSXNamespacedName'); - }; + function _class() { + _classCallCheck(this, _class); - // Parses element name in any form - namespaced, member - // or single identifier. - - pp.jsx_parseElementName = function() { - var startPos = this.start, startLoc = this.startLoc; - var node = this.jsx_parseNamespacedName(); - if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !this.options.plugins.jsx.allowNamespacedObjects) { - this.unexpected(); + return _possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).apply(this, arguments)); } - while (this.eat(tt.dot)) { - var newNode = this.startNodeAt(startPos, startLoc); - newNode.object = node; - newNode.property = this.jsx_parseIdentifier(); - node = this.finishNode(newNode, 'JSXMemberExpression'); - } - return node; - }; - // Parses any type of JSX attribute value. + _createClass(_class, [{ + key: 'jsx_readToken', - pp.jsx_parseAttributeValue = function() { - switch (this.type) { - case tt.braceL: - var node = this.jsx_parseExpressionContainer(); - if (node.expression.type === 'JSXEmptyExpression') - this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression'); - return node; + // Reads inline JSX contents token. + value: function jsx_readToken() { + var out = '', + chunkStart = this.pos; + for (;;) { + if (this.pos >= this.input.length) this.raise(this.start, 'Unterminated JSX contents'); + var ch = this.input.charCodeAt(this.pos); - case tt.jsxTagStart: - case tt.string: - return this.parseExprAtom(); + switch (ch) { + case 60: // '<' + case 123: + // '{' + if (this.pos === this.start) { + if (ch === 60 && this.exprAllowed) { + ++this.pos; + return this.finishToken(tok.jsxTagStart); + } + return this.getTokenFromCode(ch); + } + out += this.input.slice(chunkStart, this.pos); + return this.finishToken(tok.jsxText, out); - default: - this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text'); - } - }; + case 38: + // '&' + out += this.input.slice(chunkStart, this.pos); + out += this.jsx_readEntity(); + chunkStart = this.pos; + break; - // JSXEmptyExpression is unique type since it doesn't actually parse anything, - // and so it should start at the end of last read token (left brace) and finish - // at the beginning of the next one (right brace). - - pp.jsx_parseEmptyExpression = function() { - var node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc); - return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc); - }; - - // Parses JSX expression enclosed into curly brackets. - - - pp.jsx_parseExpressionContainer = function() { - var node = this.startNode(); - this.next(); - node.expression = this.type === tt.braceR - ? this.jsx_parseEmptyExpression() - : this.parseExpression(); - this.expect(tt.braceR); - return this.finishNode(node, 'JSXExpressionContainer'); - }; - - // Parses following JSX attribute name-value pair. - - pp.jsx_parseAttribute = function() { - var node = this.startNode(); - if (this.eat(tt.braceL)) { - this.expect(tt.ellipsis); - node.argument = this.parseMaybeAssign(); - this.expect(tt.braceR); - return this.finishNode(node, 'JSXSpreadAttribute'); - } - node.name = this.jsx_parseNamespacedName(); - node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null; - return this.finishNode(node, 'JSXAttribute'); - }; - - // Parses JSX opening tag starting after '<'. - - pp.jsx_parseOpeningElementAt = function(startPos, startLoc) { - var node = this.startNodeAt(startPos, startLoc); - node.attributes = []; - node.name = this.jsx_parseElementName(); - while (this.type !== tt.slash && this.type !== tt.jsxTagEnd) - node.attributes.push(this.jsx_parseAttribute()); - node.selfClosing = this.eat(tt.slash); - this.expect(tt.jsxTagEnd); - return this.finishNode(node, 'JSXOpeningElement'); - }; - - // Parses JSX closing tag starting after '= this.input.length) this.raise(this.start, 'Unterminated string constant'); + var ch = this.input.charCodeAt(this.pos); + if (ch === quote) break; + if (ch === 38) { + // '&' + out += this.input.slice(chunkStart, this.pos); + out += this.jsx_readEntity(); + chunkStart = this.pos; + } else if (isNewLine(ch)) { + out += this.input.slice(chunkStart, this.pos); + out += this.jsx_readNewLine(false); + chunkStart = this.pos; + } else { + ++this.pos; + } + } + out += this.input.slice(chunkStart, this.pos++); + return this.finishToken(tt.string, out); + } + }, { + key: 'jsx_readEntity', + value: function jsx_readEntity() { + var str = '', + count = 0, + entity = void 0; + var ch = this.input[this.pos]; + if (ch !== '&') this.raise(this.pos, 'Entity must start with an ampersand'); + var startPos = ++this.pos; + while (this.pos < this.input.length && count++ < 10) { + ch = this.input[this.pos++]; + if (ch === ';') { + if (str[0] === '#') { + if (str[1] === 'x') { + str = str.substr(2); + if (hexNumber.test(str)) entity = String.fromCharCode(parseInt(str, 16)); + } else { + str = str.substr(1); + if (decimalNumber.test(str)) entity = String.fromCharCode(parseInt(str, 10)); + } + } else { + entity = XHTMLEntities[str]; + } + break; + } + str += ch; + } + if (!entity) { + this.pos = startPos; + return '&'; + } + return entity; + } - case tt.braceL: - children.push(this.jsx_parseExpressionContainer()); - break; + // Read a JSX identifier (valid tag or attribute name). + // + // Optimized version since JSX identifiers can't contain + // escape characters and so can be read as single slice. + // Also assumes that first character was already checked + // by isIdentifierStart in readToken. - default: + }, { + key: 'jsx_readWord', + value: function jsx_readWord() { + var ch = void 0, + start = this.pos; + do { + ch = this.input.charCodeAt(++this.pos); + } while (isIdentifierChar(ch) || ch === 45); // '-' + return this.finishToken(tok.jsxName, this.input.slice(start, this.pos)); + } + + // Parse next token as JSX identifier + + }, { + key: 'jsx_parseIdentifier', + value: function jsx_parseIdentifier() { + var node = this.startNode(); + if (this.type === tok.jsxName) node.name = this.value;else if (this.type.keyword) node.name = this.type.keyword;else this.unexpected(); + this.next(); + return this.finishNode(node, 'JSXIdentifier'); + } + + // Parse namespaced identifier. + + }, { + key: 'jsx_parseNamespacedName', + value: function jsx_parseNamespacedName() { + var startPos = this.start, + startLoc = this.startLoc; + var name = this.jsx_parseIdentifier(); + if (!options.allowNamespaces || !this.eat(tt.colon)) return name; + var node = this.startNodeAt(startPos, startLoc); + node.namespace = name; + node.name = this.jsx_parseIdentifier(); + return this.finishNode(node, 'JSXNamespacedName'); + } + + // Parses element name in any form - namespaced, member + // or single identifier. + + }, { + key: 'jsx_parseElementName', + value: function jsx_parseElementName() { + if (this.type === tok.jsxTagEnd) return ''; + var startPos = this.start, + startLoc = this.startLoc; + var node = this.jsx_parseNamespacedName(); + if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) { this.unexpected(); } + while (this.eat(tt.dot)) { + var newNode = this.startNodeAt(startPos, startLoc); + newNode.object = node; + newNode.property = this.jsx_parseIdentifier(); + node = this.finishNode(newNode, 'JSXMemberExpression'); + } + return node; } - if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) { - this.raise( - closingElement.start, - 'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>'); + + // Parses any type of JSX attribute value. + + }, { + key: 'jsx_parseAttributeValue', + value: function jsx_parseAttributeValue() { + switch (this.type) { + case tt.braceL: + var node = this.jsx_parseExpressionContainer(); + if (node.expression.type === 'JSXEmptyExpression') this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression'); + return node; + + case tok.jsxTagStart: + case tt.string: + return this.parseExprAtom(); + + default: + this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text'); + } } - } - node.openingElement = openingElement; - node.closingElement = closingElement; - node.children = children; - if (this.type === tt.relational && this.value === "<") { - this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag"); - } - return this.finishNode(node, 'JSXElement'); - }; + // JSXEmptyExpression is unique type since it doesn't actually parse anything, + // and so it should start at the end of last read token (left brace) and finish + // at the beginning of the next one (right brace). - // Parses entire JSX element from current position. + }, { + key: 'jsx_parseEmptyExpression', + value: function jsx_parseEmptyExpression() { + var node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc); + return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc); + } - pp.jsx_parseElement = function() { - var startPos = this.start, startLoc = this.startLoc; - this.next(); - return this.jsx_parseElementAt(startPos, startLoc); - }; + // Parses JSX expression enclosed into curly brackets. - acorn.plugins.jsx = function(instance, opts) { - if (!opts) { - return; - } + }, { + key: 'jsx_parseExpressionContainer', + value: function jsx_parseExpressionContainer() { + var node = this.startNode(); + this.next(); + node.expression = this.type === tt.braceR ? this.jsx_parseEmptyExpression() : this.parseExpression(); + this.expect(tt.braceR); + return this.finishNode(node, 'JSXExpressionContainer'); + } - if (typeof opts !== 'object') { - opts = {}; - } + // Parses following JSX attribute name-value pair. - instance.options.plugins.jsx = { - allowNamespaces: opts.allowNamespaces !== false, - allowNamespacedObjects: !!opts.allowNamespacedObjects - }; + }, { + key: 'jsx_parseAttribute', + value: function jsx_parseAttribute() { + var node = this.startNode(); + if (this.eat(tt.braceL)) { + this.expect(tt.ellipsis); + node.argument = this.parseMaybeAssign(); + this.expect(tt.braceR); + return this.finishNode(node, 'JSXSpreadAttribute'); + } + node.name = this.jsx_parseNamespacedName(); + node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null; + return this.finishNode(node, 'JSXAttribute'); + } - instance.extend('parseExprAtom', function(inner) { - return function(refShortHandDefaultPos) { - if (this.type === tt.jsxText) - return this.parseLiteral(this.value); - else if (this.type === tt.jsxTagStart) - return this.jsx_parseElement(); - else - return inner.call(this, refShortHandDefaultPos); - }; - }); + // Parses JSX opening tag starting after '<'. - instance.extend('readToken', function(inner) { - return function(code) { + }, { + key: 'jsx_parseOpeningElementAt', + value: function jsx_parseOpeningElementAt(startPos, startLoc) { + var node = this.startNodeAt(startPos, startLoc); + node.attributes = []; + var nodeName = this.jsx_parseElementName(); + if (nodeName) node.name = nodeName; + while (this.type !== tt.slash && this.type !== tok.jsxTagEnd) { + node.attributes.push(this.jsx_parseAttribute()); + }node.selfClosing = this.eat(tt.slash); + this.expect(tok.jsxTagEnd); + return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment'); + } + + // Parses JSX closing tag starting after ''); + } + } + var fragmentOrElement = openingElement.name ? 'Element' : 'Fragment'; + + node['opening' + fragmentOrElement] = openingElement; + node['closing' + fragmentOrElement] = closingElement; + node.children = children; + if (this.type === tt.relational && this.value === "<") { + this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag"); + } + return this.finishNode(node, 'JSX' + fragmentOrElement); + } + + // Parse JSX text + + }, { + key: 'jsx_parseText', + value: function jsx_parseText(value) { + var node = this.parseLiteral(value); + node.type = "JSXText"; + return node; + } + + // Parses entire JSX element from current position. + + }, { + key: 'jsx_parseElement', + value: function jsx_parseElement() { + var startPos = this.start, + startLoc = this.startLoc; + this.next(); + return this.jsx_parseElementAt(startPos, startLoc); + } + }, { + key: 'parseExprAtom', + value: function parseExprAtom(refShortHandDefaultPos) { + if (this.type === tok.jsxText) return this.jsx_parseText(this.value);else if (this.type === tok.jsxTagStart) return this.jsx_parseElement();else return _get(_class.prototype.__proto__ || Object.getPrototypeOf(_class.prototype), 'parseExprAtom', this).call(this, refShortHandDefaultPos); + } + }, { + key: 'readToken', + value: function readToken(code) { var context = this.curContext(); - if (context === tc.j_expr) return this.jsx_readToken(); + if (context === tc_expr) return this.jsx_readToken(); - if (context === tc.j_oTag || context === tc.j_cTag) { - if (acorn.isIdentifierStart(code)) return this.jsx_readWord(); + if (context === tc_oTag || context === tc_cTag) { + if (isIdentifierStart(code)) return this.jsx_readWord(); if (code == 62) { ++this.pos; - return this.finishToken(tt.jsxTagEnd); + return this.finishToken(tok.jsxTagEnd); } - if ((code === 34 || code === 39) && context == tc.j_oTag) - return this.jsx_readString(code); + if ((code === 34 || code === 39) && context == tc_oTag) return this.jsx_readString(code); } - if (code === 60 && this.exprAllowed) { + if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) { ++this.pos; - return this.finishToken(tt.jsxTagStart); + return this.finishToken(tok.jsxTagStart); } - return inner.call(this, code); - }; - }); - - instance.extend('updateContext', function(inner) { - return function(prevType) { + return _get(_class.prototype.__proto__ || Object.getPrototypeOf(_class.prototype), 'readToken', this).call(this, code); + } + }, { + key: 'updateContext', + value: function updateContext(prevType) { if (this.type == tt.braceL) { var curContext = this.curContext(); - if (curContext == tc.j_oTag) this.context.push(tc.b_expr); - else if (curContext == tc.j_expr) this.context.push(tc.b_tmpl); - else inner.call(this, prevType); + if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);else _get(_class.prototype.__proto__ || Object.getPrototypeOf(_class.prototype), 'updateContext', this).call(this, prevType); this.exprAllowed = true; - } else if (this.type === tt.slash && prevType === tt.jsxTagStart) { + } else if (this.type === tt.slash && prevType === tok.jsxTagStart) { this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore - this.context.push(tc.j_cTag); // reconsider as closing tag context + this.context.push(tc_cTag); // reconsider as closing tag context this.exprAllowed = false; } else { - return inner.call(this, prevType); + return _get(_class.prototype.__proto__ || Object.getPrototypeOf(_class.prototype), 'updateContext', this).call(this, prevType); } - }; - }); - }; + } + }]); - return acorn; -}; + return _class; + }(Parser); +} + +},{"./xhtml":2,"acorn":3}],2:[function(require,module,exports){ +'use strict'; -},{"./xhtml":2}],2:[function(require,module,exports){ module.exports = { - quot: '\u0022', + quot: '"', amp: '&', - apos: '\u0027', + apos: '\'', lt: '<', gt: '>', - nbsp: '\u00A0', - iexcl: '\u00A1', - cent: '\u00A2', - pound: '\u00A3', - curren: '\u00A4', - yen: '\u00A5', - brvbar: '\u00A6', - sect: '\u00A7', - uml: '\u00A8', - copy: '\u00A9', - ordf: '\u00AA', - laquo: '\u00AB', - not: '\u00AC', - shy: '\u00AD', - reg: '\u00AE', - macr: '\u00AF', - deg: '\u00B0', - plusmn: '\u00B1', - sup2: '\u00B2', - sup3: '\u00B3', - acute: '\u00B4', - micro: '\u00B5', - para: '\u00B6', - middot: '\u00B7', - cedil: '\u00B8', - sup1: '\u00B9', - ordm: '\u00BA', - raquo: '\u00BB', - frac14: '\u00BC', - frac12: '\u00BD', - frac34: '\u00BE', - iquest: '\u00BF', - Agrave: '\u00C0', - Aacute: '\u00C1', - Acirc: '\u00C2', - Atilde: '\u00C3', - Auml: '\u00C4', - Aring: '\u00C5', - AElig: '\u00C6', - Ccedil: '\u00C7', - Egrave: '\u00C8', - Eacute: '\u00C9', - Ecirc: '\u00CA', - Euml: '\u00CB', - Igrave: '\u00CC', - Iacute: '\u00CD', - Icirc: '\u00CE', - Iuml: '\u00CF', - ETH: '\u00D0', - Ntilde: '\u00D1', - Ograve: '\u00D2', - Oacute: '\u00D3', - Ocirc: '\u00D4', - Otilde: '\u00D5', - Ouml: '\u00D6', - times: '\u00D7', - Oslash: '\u00D8', - Ugrave: '\u00D9', - Uacute: '\u00DA', - Ucirc: '\u00DB', - Uuml: '\u00DC', - Yacute: '\u00DD', - THORN: '\u00DE', - szlig: '\u00DF', - agrave: '\u00E0', - aacute: '\u00E1', - acirc: '\u00E2', - atilde: '\u00E3', - auml: '\u00E4', - aring: '\u00E5', - aelig: '\u00E6', - ccedil: '\u00E7', - egrave: '\u00E8', - eacute: '\u00E9', - ecirc: '\u00EA', - euml: '\u00EB', - igrave: '\u00EC', - iacute: '\u00ED', - icirc: '\u00EE', - iuml: '\u00EF', - eth: '\u00F0', - ntilde: '\u00F1', - ograve: '\u00F2', - oacute: '\u00F3', - ocirc: '\u00F4', - otilde: '\u00F5', - ouml: '\u00F6', - divide: '\u00F7', - oslash: '\u00F8', - ugrave: '\u00F9', - uacute: '\u00FA', - ucirc: '\u00FB', - uuml: '\u00FC', - yacute: '\u00FD', - thorn: '\u00FE', - yuml: '\u00FF', + nbsp: '\xA0', + iexcl: '\xA1', + cent: '\xA2', + pound: '\xA3', + curren: '\xA4', + yen: '\xA5', + brvbar: '\xA6', + sect: '\xA7', + uml: '\xA8', + copy: '\xA9', + ordf: '\xAA', + laquo: '\xAB', + not: '\xAC', + shy: '\xAD', + reg: '\xAE', + macr: '\xAF', + deg: '\xB0', + plusmn: '\xB1', + sup2: '\xB2', + sup3: '\xB3', + acute: '\xB4', + micro: '\xB5', + para: '\xB6', + middot: '\xB7', + cedil: '\xB8', + sup1: '\xB9', + ordm: '\xBA', + raquo: '\xBB', + frac14: '\xBC', + frac12: '\xBD', + frac34: '\xBE', + iquest: '\xBF', + Agrave: '\xC0', + Aacute: '\xC1', + Acirc: '\xC2', + Atilde: '\xC3', + Auml: '\xC4', + Aring: '\xC5', + AElig: '\xC6', + Ccedil: '\xC7', + Egrave: '\xC8', + Eacute: '\xC9', + Ecirc: '\xCA', + Euml: '\xCB', + Igrave: '\xCC', + Iacute: '\xCD', + Icirc: '\xCE', + Iuml: '\xCF', + ETH: '\xD0', + Ntilde: '\xD1', + Ograve: '\xD2', + Oacute: '\xD3', + Ocirc: '\xD4', + Otilde: '\xD5', + Ouml: '\xD6', + times: '\xD7', + Oslash: '\xD8', + Ugrave: '\xD9', + Uacute: '\xDA', + Ucirc: '\xDB', + Uuml: '\xDC', + Yacute: '\xDD', + THORN: '\xDE', + szlig: '\xDF', + agrave: '\xE0', + aacute: '\xE1', + acirc: '\xE2', + atilde: '\xE3', + auml: '\xE4', + aring: '\xE5', + aelig: '\xE6', + ccedil: '\xE7', + egrave: '\xE8', + eacute: '\xE9', + ecirc: '\xEA', + euml: '\xEB', + igrave: '\xEC', + iacute: '\xED', + icirc: '\xEE', + iuml: '\xEF', + eth: '\xF0', + ntilde: '\xF1', + ograve: '\xF2', + oacute: '\xF3', + ocirc: '\xF4', + otilde: '\xF5', + ouml: '\xF6', + divide: '\xF7', + oslash: '\xF8', + ugrave: '\xF9', + uacute: '\xFA', + ucirc: '\xFB', + uuml: '\xFC', + yacute: '\xFD', + thorn: '\xFE', + yuml: '\xFF', OElig: '\u0152', oelig: '\u0153', Scaron: '\u0160', @@ -8265,3873 +8314,5828 @@ module.exports = { }; },{}],3:[function(require,module,exports){ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.acorn = {}))); -}(this, (function (exports) { 'use strict'; - -// Reserved word lists for various dialects of the language - -var reservedWords = { - 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", - 5: "class enum extends super const export import", - 6: "enum", - strict: "implements interface let package private protected public static yield", - strictBind: "eval arguments" -}; - -// And the keywords - -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"; - -var keywords = { - 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " const class extends export import super" -}; - -var keywordRelationalOperator = /^in(stanceof)?$/; - -// ## Character categories - -// Big ugly regular expressions that match characters in the -// whitespace, identifier, and identifier-start categories. These -// are only applied when a character is found to actually have a -// code point above 128. -// Generated by `bin/generate-identifier-regex.js`. - -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\u0561-\u0587\u05d0-\u05ea\u05f0-\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\u08a0-\u08b4\u08b6-\u08bd\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\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\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\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\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\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-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\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-\u2c2e\u2c30-\u2c5e\u2c60-\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-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\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-\uab65\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"; -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\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\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\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\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\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\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\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-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\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\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\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\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\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"; - -var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; - -// These are a run-length and offset encoded representation of the -// >0xffff code points that are a valid part of identifiers. The -// offset starts at 0x10000, and each pair of numbers represents an -// offset to the next range, and then a size of the range. They were -// generated by bin/generate-identifier-regex.js - -// eslint-disable-next-line comma-spacing -var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,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,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,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,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,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,4149,196,60,67,1213,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,42710,42,4148,12,221,3,5761,10591,541]; - -// eslint-disable-next-line comma-spacing -var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,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,2214,6,110,6,6,9,792487,239]; - -// This has a complexity linear to the value of the code. The -// assumption is that looking up astral identifier characters is -// rare. -function isInAstralSet(code, set) { - var pos = 0x10000; - for (var i = 0; i < set.length; i += 2) { - pos += set[i]; - if (pos > code) { return false } - pos += set[i + 1]; - if (pos >= code) { return true } - } -} - -// Test whether a given character code starts an identifier. - -function isIdentifierStart(code, astral) { - if (code < 65) { return code === 36 } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) -} - -// Test whether a given character is part of an identifier. - -function isIdentifierChar(code, astral) { - if (code < 48) { return code === 36 } - if (code < 58) { return true } - if (code < 65) { return false } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) -} - -// ## Token types - -// The assignment of fine-grained, information-carrying type objects -// allows the tokenizer to store the information it has about a -// token in a way that is very cheap for the parser to look up. - -// All token type variables start with an underscore, to make them -// easy to recognize. - -// The `beforeExpr` property is used to disambiguate between regular -// expressions and divisions. It is set on all token types that can -// be followed by an expression (thus, a slash after them would be a -// regular expression). -// -// The `startsExpr` property is used to check if the token ends a -// `yield` expression. It is set on all token types that either can -// directly start an expression (like a quotation mark) or can -// continue an expression (like the body of a string). -// -// `isLoop` marks a keyword as starting a loop, which is important -// to know when parsing a label, in order to allow or disallow -// continue jumps to that label. - -var TokenType = function TokenType(label, conf) { - if ( conf === void 0 ) conf = {}; - - this.label = label; - this.keyword = conf.keyword; - this.beforeExpr = !!conf.beforeExpr; - this.startsExpr = !!conf.startsExpr; - this.isLoop = !!conf.isLoop; - this.isAssign = !!conf.isAssign; - this.prefix = !!conf.prefix; - this.postfix = !!conf.postfix; - this.binop = conf.binop || null; - this.updateContext = null; -}; - -function binop(name, prec) { - return new TokenType(name, {beforeExpr: true, binop: prec}) -} -var beforeExpr = {beforeExpr: true}; -var startsExpr = {startsExpr: true}; - -// Map keyword names to token types. - -var keywords$1 = {}; - -// Succinct definitions of keyword token types -function kw(name, options) { - if ( options === void 0 ) options = {}; - - options.keyword = name; - return keywords$1[name] = new TokenType(name, options) -} - -var types = { - num: new TokenType("num", startsExpr), - regexp: new TokenType("regexp", startsExpr), - string: new TokenType("string", startsExpr), - name: new TokenType("name", startsExpr), - eof: new TokenType("eof"), - - // Punctuation token types. - bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), - bracketR: new TokenType("]"), - braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), - braceR: new TokenType("}"), - parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), - parenR: new TokenType(")"), - comma: new TokenType(",", beforeExpr), - semi: new TokenType(";", beforeExpr), - colon: new TokenType(":", beforeExpr), - dot: new TokenType("."), - question: new TokenType("?", beforeExpr), - arrow: new TokenType("=>", beforeExpr), - template: new TokenType("template"), - invalidTemplate: new TokenType("invalidTemplate"), - ellipsis: new TokenType("...", beforeExpr), - backQuote: new TokenType("`", startsExpr), - dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), - - // Operators. These carry several kinds of properties to help the - // parser use them properly (the presence of these properties is - // what categorizes them as operators). - // - // `binop`, when present, specifies that this operator is a binary - // operator, and will refer to its precedence. - // - // `prefix` and `postfix` mark the operator as a prefix or postfix - // unary operator. - // - // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as - // binary operators with a very low precedence, that should result - // in AssignmentExpression nodes. - - eq: new TokenType("=", {beforeExpr: true, isAssign: true}), - assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), - incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), - prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), - logicalOR: binop("||", 1), - logicalAND: binop("&&", 2), - bitwiseOR: binop("|", 3), - bitwiseXOR: binop("^", 4), - bitwiseAND: binop("&", 5), - equality: binop("==/!=/===/!==", 6), - relational: binop("/<=/>=", 7), - bitShift: binop("<>/>>>", 8), - plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), - modulo: binop("%", 10), - star: binop("*", 10), - slash: binop("/", 10), - starstar: new TokenType("**", {beforeExpr: true}), - - // Keyword token types. - _break: kw("break"), - _case: kw("case", beforeExpr), - _catch: kw("catch"), - _continue: kw("continue"), - _debugger: kw("debugger"), - _default: kw("default", beforeExpr), - _do: kw("do", {isLoop: true, beforeExpr: true}), - _else: kw("else", beforeExpr), - _finally: kw("finally"), - _for: kw("for", {isLoop: true}), - _function: kw("function", startsExpr), - _if: kw("if"), - _return: kw("return", beforeExpr), - _switch: kw("switch"), - _throw: kw("throw", beforeExpr), - _try: kw("try"), - _var: kw("var"), - _const: kw("const"), - _while: kw("while", {isLoop: true}), - _with: kw("with"), - _new: kw("new", {beforeExpr: true, startsExpr: true}), - _this: kw("this", startsExpr), - _super: kw("super", startsExpr), - _class: kw("class", startsExpr), - _extends: kw("extends", beforeExpr), - _export: kw("export"), - _import: kw("import"), - _null: kw("null", startsExpr), - _true: kw("true", startsExpr), - _false: kw("false", startsExpr), - _in: kw("in", {beforeExpr: true, binop: 7}), - _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), - _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), - _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), - _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) -}; - -// Matches a whole line break (where CRLF is considered a single -// line break). Used to count lines. - -var lineBreak = /\r\n?|\n|\u2028|\u2029/; -var lineBreakG = new RegExp(lineBreak.source, "g"); - -function isNewLine(code) { - return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 -} - -var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; - -var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; - -var ref = Object.prototype; -var hasOwnProperty = ref.hasOwnProperty; -var toString = ref.toString; - -// Checks if an object has a property. - -function has(obj, propName) { - return hasOwnProperty.call(obj, propName) -} - -var isArray = Array.isArray || (function (obj) { return ( - toString.call(obj) === "[object Array]" -); }); - -// These are used when `options.locations` is on, for the -// `startLoc` and `endLoc` properties. - -var Position = function Position(line, col) { - this.line = line; - this.column = col; -}; - -Position.prototype.offset = function offset (n) { - return new Position(this.line, this.column + n) -}; - -var SourceLocation = function SourceLocation(p, start, end) { - this.start = start; - this.end = end; - if (p.sourceFile !== null) { this.source = p.sourceFile; } -}; - -// The `getLineInfo` function is mostly useful when the -// `locations` option is off (for performance reasons) and you -// want to find the line/column position for a given character -// offset. `input` should be the code string that the offset refers -// into. - -function getLineInfo(input, offset) { - for (var line = 1, cur = 0;;) { - lineBreakG.lastIndex = cur; - var match = lineBreakG.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else { - return new Position(line, offset - cur) - } - } -} - -// A second optional argument can be given to further configure -// the parser process. These options are recognized: - -var defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support - // for strict mode, the set of reserved words, and support for - // new syntax features. The default is 7. - ecmaVersion: 7, - // `sourceType` indicates the mode the code should be parsed in. - // Can be either `"script"` or `"module"`. This influences global - // strict mode and parsing of `import` and `export` declarations. - sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. - onInsertedSemicolon: null, - // `onTrailingComma` is similar to `onInsertedSemicolon`, but for - // trailing commas. - onTrailingComma: null, - // By default, reserved words are only enforced if ecmaVersion >= 5. - // Set `allowReserved` to a boolean value to explicitly turn this on - // an off. When this option has the value "never", reserved words - // and keywords can also not be used as property names. - allowReserved: null, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When enabled, import/export statements are not constrained to - // appearing at the top of the program. - allowImportExportEverywhere: false, - // When enabled, hashbang directive in the beginning of file - // is allowed and treated as a line comment. - allowHashBang: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onToken` option, which will - // cause Acorn to call that function with object in the same - // format as tokens returned from `tokenizer().getToken()`. Note - // that you are not allowed to call the parser from the - // callback—that will corrupt its internal state. - onToken: null, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null, - // When enabled, parenthesized expressions are represented by - // (non-standard) ParenthesizedExpression nodes - preserveParens: false, - plugins: {} -}; - -// Interpret and default an options object - -function getOptions(opts) { - var options = {}; - - for (var opt in defaultOptions) - { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } - - if (options.ecmaVersion >= 2015) - { options.ecmaVersion -= 2009; } - - if (options.allowReserved == null) - { options.allowReserved = options.ecmaVersion < 5; } - - if (isArray(options.onToken)) { - var tokens = options.onToken; - options.onToken = function (token) { return tokens.push(token); }; - } - if (isArray(options.onComment)) - { options.onComment = pushComment(options, options.onComment); } - - return options -} - -function pushComment(options, array) { - return function(block, text, start, end, startLoc, endLoc) { - var comment = { - type: block ? "Block" : "Line", - value: text, - start: start, - end: end - }; - if (options.locations) - { comment.loc = new SourceLocation(this, startLoc, endLoc); } - if (options.ranges) - { comment.range = [start, end]; } - array.push(comment); - } -} - -// Registered plugins -var plugins = {}; - -function keywordRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") -} - -var Parser = function Parser(options, input, startPos) { - this.options = options = getOptions(options); - this.sourceFile = options.sourceFile; - this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); - var reserved = ""; - if (!options.allowReserved) { - for (var v = options.ecmaVersion;; v--) - { if (reserved = reservedWords[v]) { break } } - if (options.sourceType == "module") { reserved += " await"; } - } - this.reservedWords = keywordRegexp(reserved); - var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; - this.reservedWordsStrict = keywordRegexp(reservedStrict); - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); - this.input = String(input); - - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - this.containsEsc = false; - - // Load plugins - this.loadPlugins(options.plugins); - - // Set up token state - - // The current position of the tokenizer in the input. - if (startPos) { - this.pos = startPos; - this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; - this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; - } else { - this.pos = this.lineStart = 0; - this.curLine = 1; - } - - // Properties of the current token: - // Its type - this.type = types.eof; - // For tokens that include more information than their type, the value - this.value = null; - // Its start and end offset - this.start = this.end = this.pos; - // And, if locations are used, the {line, column} object - // corresponding to those offsets - this.startLoc = this.endLoc = this.curPosition(); - - // Position information for the previous token - this.lastTokEndLoc = this.lastTokStartLoc = null; - this.lastTokStart = this.lastTokEnd = this.pos; - - // The context stack is used to superficially track syntactic - // context to predict whether a regular expression is allowed in a - // given position. - this.context = this.initialContext(); - this.exprAllowed = true; - - // Figure out if it's a module code. - this.inModule = options.sourceType === "module"; - this.strict = this.inModule || this.strictDirective(this.pos); - - // Used to signify the start of a potential arrow function - this.potentialArrowAt = -1; - - // Flags to track whether we are in a function, a generator, an async function. - this.inFunction = this.inGenerator = this.inAsync = false; - // Positions to delayed-check that yield/await does not exist in default parameters. - this.yieldPos = this.awaitPos = 0; - // Labels in scope. - this.labels = []; - - // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") - { this.skipLineComment(2); } - - // Scope tracking for duplicate variable names (see scope.js) - this.scopeStack = []; - this.enterFunctionScope(); -}; - -// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them -Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; -Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; - -Parser.prototype.extend = function extend (name, f) { - this[name] = f(this[name]); -}; - -Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { - var this$1 = this; - - for (var name in pluginConfigs) { - var plugin = plugins[name]; - if (!plugin) { throw new Error("Plugin '" + name + "' not found") } - plugin(this$1, pluginConfigs[name]); - } -}; - -Parser.prototype.parse = function parse () { - var node = this.options.program || this.startNode(); - this.nextToken(); - return this.parseTopLevel(node) -}; - -var pp = Parser.prototype; - -// ## Parser utilities - -var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; -pp.strictDirective = function(start) { - var this$1 = this; - - for (;;) { - skipWhiteSpace.lastIndex = start; - start += skipWhiteSpace.exec(this$1.input)[0].length; - var match = literal.exec(this$1.input.slice(start)); - if (!match) { return false } - if ((match[1] || match[2]) == "use strict") { return true } - start += match[0].length; - } -}; - -// Predicate that tests whether the next token is of the given -// type, and if yes, consumes it as a side effect. - -pp.eat = function(type) { - if (this.type === type) { - this.next(); - return true - } else { - return false - } -}; - -// Tests whether parsed token is a contextual keyword. - -pp.isContextual = function(name) { - return this.type === types.name && this.value === name && !this.containsEsc -}; - -// Consumes contextual keyword if possible. - -pp.eatContextual = function(name) { - if (!this.isContextual(name)) { return false } - this.next(); - return true -}; - -// Asserts that following token is given contextual keyword. - -pp.expectContextual = function(name) { - if (!this.eatContextual(name)) { this.unexpected(); } -}; - -// Test whether a semicolon can be inserted at the current position. - -pp.canInsertSemicolon = function() { - return this.type === types.eof || - this.type === types.braceR || - lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -pp.insertSemicolon = function() { - if (this.canInsertSemicolon()) { - if (this.options.onInsertedSemicolon) - { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } - return true - } -}; - -// Consume a semicolon, or, failing that, see if we are allowed to -// pretend that there is a semicolon at this position. - -pp.semicolon = function() { - if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } -}; - -pp.afterTrailingComma = function(tokType, notNext) { - if (this.type == tokType) { - if (this.options.onTrailingComma) - { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } - if (!notNext) - { this.next(); } - return true - } -}; - -// Expect a token of a given type. If found, consume it, otherwise, -// raise an unexpected token error. - -pp.expect = function(type) { - this.eat(type) || this.unexpected(); -}; - -// Raise an unexpected token error. - -pp.unexpected = function(pos) { - this.raise(pos != null ? pos : this.start, "Unexpected token"); -}; - -function DestructuringErrors() { - this.shorthandAssign = - this.trailingComma = - this.parenthesizedAssign = - this.parenthesizedBind = - this.doubleProto = - -1; -} - -pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { - if (!refDestructuringErrors) { return } - if (refDestructuringErrors.trailingComma > -1) - { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } - var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; - if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } -}; - -pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - if (!refDestructuringErrors) { return false } - var shorthandAssign = refDestructuringErrors.shorthandAssign; - var doubleProto = refDestructuringErrors.doubleProto; - if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } - if (shorthandAssign >= 0) - { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } - if (doubleProto >= 0) - { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } -}; - -pp.checkYieldAwaitInDefaultParams = function() { - if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) - { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } - if (this.awaitPos) - { this.raise(this.awaitPos, "Await expression cannot be a default value"); } -}; - -pp.isSimpleAssignTarget = function(expr) { - if (expr.type === "ParenthesizedExpression") - { return this.isSimpleAssignTarget(expr.expression) } - return expr.type === "Identifier" || expr.type === "MemberExpression" -}; - -var pp$1 = Parser.prototype; - -// ### Statement parsing - -// Parse a program. Initializes the parser, reads any number of -// statements, and wraps them in a Program node. Optionally takes a -// `program` argument. If present, the statements will be appended -// to its body instead of creating a new node. - -pp$1.parseTopLevel = function(node) { - var this$1 = this; - - var exports = {}; - if (!node.body) { node.body = []; } - while (this.type !== types.eof) { - var stmt = this$1.parseStatement(true, true, exports); - node.body.push(stmt); - } - this.adaptDirectivePrologue(node.body); - this.next(); - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program") -}; - -var loopLabel = {kind: "loop"}; -var switchLabel = {kind: "switch"}; - -pp$1.isLet = function() { - if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); - if (nextCh === 91 || nextCh == 123) { return true } // '{' and '[' - if (isIdentifierStart(nextCh, true)) { - var pos = next + 1; - while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } - var ident = this.input.slice(next, pos); - if (!keywordRelationalOperator.test(ident)) { return true } - } - return false -}; - -// check 'async [no LineTerminator here] function' -// - 'async /*foo*/ function' is OK. -// - 'async /*\n*/ function' is invalid. -pp$1.isAsyncFunction = function() { - if (this.options.ecmaVersion < 8 || !this.isContextual("async")) - { return false } - - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length; - return !lineBreak.test(this.input.slice(this.pos, next)) && - this.input.slice(next, next + 8) === "function" && - (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) -}; - -// Parse a single statement. -// -// If expecting a statement and finding a slash operator, parse a -// regular expression literal. This is to handle cases like -// `if (foo) /blah/.exec(foo)`, where looking at the previous token -// does not help. - -pp$1.parseStatement = function(declaration, topLevel, exports) { - var starttype = this.type, node = this.startNode(), kind; - - if (this.isLet()) { - starttype = types._var; - kind = "let"; - } - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) - case types._debugger: return this.parseDebuggerStatement(node) - case types._do: return this.parseDoStatement(node) - case types._for: return this.parseForStatement(node) - case types._function: - if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } - return this.parseFunctionStatement(node, false) - case types._class: - if (!declaration) { this.unexpected(); } - return this.parseClass(node, true) - case types._if: return this.parseIfStatement(node) - case types._return: return this.parseReturnStatement(node) - case types._switch: return this.parseSwitchStatement(node) - case types._throw: return this.parseThrowStatement(node) - case types._try: return this.parseTryStatement(node) - case types._const: case types._var: - kind = kind || this.value; - if (!declaration && kind != "var") { this.unexpected(); } - return this.parseVarStatement(node, kind) - case types._while: return this.parseWhileStatement(node) - case types._with: return this.parseWithStatement(node) - case types.braceL: return this.parseBlock() - case types.semi: return this.parseEmptyStatement(node) - case types._export: - case types._import: - if (!this.options.allowImportExportEverywhere) { - if (!topLevel) - { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } - if (!this.inModule) - { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } - } - return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) - - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - default: - if (this.isAsyncFunction()) { - if (!declaration) { this.unexpected(); } - this.next(); - return this.parseFunctionStatement(node, true) - } - - var maybeName = this.value, expr = this.parseExpression(); - if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) - { return this.parseLabeledStatement(node, maybeName, expr) } - else { return this.parseExpressionStatement(node, expr) } - } -}; - -pp$1.parseBreakContinueStatement = function(node, keyword) { - var this$1 = this; - - var isBreak = keyword == "break"; - this.next(); - if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } - else if (this.type !== types.name) { this.unexpected(); } - else { - node.label = this.parseIdent(); - this.semicolon(); - } - - // Verify that there is an actual destination to break or - // continue to. - var i = 0; - for (; i < this.labels.length; ++i) { - var lab = this$1.labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } - if (node.label && isBreak) { break } - } - } - if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") -}; - -pp$1.parseDebuggerStatement = function(node) { - this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement") -}; - -pp$1.parseDoStatement = function(node) { - this.next(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - this.expect(types._while); - node.test = this.parseParenExpression(); - if (this.options.ecmaVersion >= 6) - { this.eat(types.semi); } - else - { this.semicolon(); } - return this.finishNode(node, "DoWhileStatement") -}; - -// Disambiguating between a `for` and a `for`/`in` or `for`/`of` -// loop is non-trivial. Basically, we have to parse the init `var` -// statement or expression, disallowing the `in` operator (see -// the second parameter to `parseExpression`), and then check -// whether the next token is `in` or `of`. When there is no init -// part (semicolon immediately after the opening parenthesis), it -// is a regular `for` loop. - -pp$1.parseForStatement = function(node) { - this.next(); - var awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1; - this.labels.push(loopLabel); - this.enterLexicalScope(); - this.expect(types.parenL); - if (this.type === types.semi) { - if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, null) - } - var isLet = this.isLet(); - if (this.type === types._var || this.type === types._const || isLet) { - var init$1 = this.startNode(), kind = isLet ? "let" : this.value; - this.next(); - this.parseVar(init$1, true, kind); - this.finishNode(init$1, "VariableDeclaration"); - if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && - !(kind !== "var" && init$1.declarations[0].init)) { - if (this.options.ecmaVersion >= 9) { - if (this.type === types._in) { - if (awaitAt > -1) { this.unexpected(awaitAt); } - } else { node.await = awaitAt > -1; } - } - return this.parseForIn(node, init$1) - } - if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, init$1) - } - var refDestructuringErrors = new DestructuringErrors; - var init = this.parseExpression(true, refDestructuringErrors); - if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - if (this.options.ecmaVersion >= 9) { - if (this.type === types._in) { - if (awaitAt > -1) { this.unexpected(awaitAt); } - } else { node.await = awaitAt > -1; } - } - this.toAssignable(init, false, refDestructuringErrors); - this.checkLVal(init); - return this.parseForIn(node, init) - } else { - this.checkExpressionErrors(refDestructuringErrors, true); - } - if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, init) -}; - -pp$1.parseFunctionStatement = function(node, isAsync) { - this.next(); - return this.parseFunction(node, true, false, isAsync) -}; - -pp$1.parseIfStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - // allow function declarations in branches, but only in non-strict mode - node.consequent = this.parseStatement(!this.strict && this.type == types._function); - node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type == types._function) : null; - return this.finishNode(node, "IfStatement") -}; - -pp$1.parseReturnStatement = function(node) { - if (!this.inFunction && !this.options.allowReturnOutsideFunction) - { this.raise(this.start, "'return' outside of function"); } - this.next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } - else { node.argument = this.parseExpression(); this.semicolon(); } - return this.finishNode(node, "ReturnStatement") -}; - -pp$1.parseSwitchStatement = function(node) { - var this$1 = this; - - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; - this.expect(types.braceL); - this.labels.push(switchLabel); - this.enterLexicalScope(); - - // Statements under must be grouped (by label) in SwitchCase - // nodes. `cur` is used to keep the node that we are currently - // adding statements to. - - var cur; - for (var sawDefault = false; this.type != types.braceR;) { - if (this$1.type === types._case || this$1.type === types._default) { - var isCase = this$1.type === types._case; - if (cur) { this$1.finishNode(cur, "SwitchCase"); } - node.cases.push(cur = this$1.startNode()); - cur.consequent = []; - this$1.next(); - if (isCase) { - cur.test = this$1.parseExpression(); - } else { - if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } - sawDefault = true; - cur.test = null; - } - this$1.expect(types.colon); - } else { - if (!cur) { this$1.unexpected(); } - cur.consequent.push(this$1.parseStatement(true)); - } - } - this.exitLexicalScope(); - if (cur) { this.finishNode(cur, "SwitchCase"); } - this.next(); // Closing brace - this.labels.pop(); - return this.finishNode(node, "SwitchStatement") -}; - -pp$1.parseThrowStatement = function(node) { - this.next(); - if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) - { this.raise(this.lastTokEnd, "Illegal newline after throw"); } - node.argument = this.parseExpression(); - this.semicolon(); - return this.finishNode(node, "ThrowStatement") -}; - -// Reused empty array added for node fields that are always empty. - -var empty = []; - -pp$1.parseTryStatement = function(node) { - this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.type === types._catch) { - var clause = this.startNode(); - this.next(); - this.expect(types.parenL); - clause.param = this.parseBindingAtom(); - this.enterLexicalScope(); - this.checkLVal(clause.param, "let"); - this.expect(types.parenR); - clause.body = this.parseBlock(false); - this.exitLexicalScope(); - node.handler = this.finishNode(clause, "CatchClause"); - } - node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) - { this.raise(node.start, "Missing catch or finally clause"); } - return this.finishNode(node, "TryStatement") -}; - -pp$1.parseVarStatement = function(node, kind) { - this.next(); - this.parseVar(node, false, kind); - this.semicolon(); - return this.finishNode(node, "VariableDeclaration") -}; - -pp$1.parseWhileStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "WhileStatement") -}; - -pp$1.parseWithStatement = function(node) { - if (this.strict) { this.raise(this.start, "'with' in strict mode"); } - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement(false); - return this.finishNode(node, "WithStatement") -}; - -pp$1.parseEmptyStatement = function(node) { - this.next(); - return this.finishNode(node, "EmptyStatement") -}; - -pp$1.parseLabeledStatement = function(node, maybeName, expr) { - var this$1 = this; - - for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) - { - var label = list[i$1]; - - if (label.name === maybeName) - { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); - } } - var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; - for (var i = this.labels.length - 1; i >= 0; i--) { - var label$1 = this$1.labels[i]; - if (label$1.statementStart == node.start) { - // Update information about previous labels on this node - label$1.statementStart = this$1.start; - label$1.kind = kind; - } else { break } - } - this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); - node.body = this.parseStatement(true); - if (node.body.type == "ClassDeclaration" || - node.body.type == "VariableDeclaration" && node.body.kind != "var" || - node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) - { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } - this.labels.pop(); - node.label = expr; - return this.finishNode(node, "LabeledStatement") -}; - -pp$1.parseExpressionStatement = function(node, expr) { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement") -}; - -// Parse a semicolon-enclosed block of statements, handling `"use -// strict"` declarations when `allowStrict` is true (used for -// function bodies). - -pp$1.parseBlock = function(createNewLexicalScope) { - var this$1 = this; - if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; - - var node = this.startNode(); - node.body = []; - this.expect(types.braceL); - if (createNewLexicalScope) { - this.enterLexicalScope(); - } - while (!this.eat(types.braceR)) { - var stmt = this$1.parseStatement(true); - node.body.push(stmt); - } - if (createNewLexicalScope) { - this.exitLexicalScope(); - } - return this.finishNode(node, "BlockStatement") -}; - -// Parse a regular `for` loop. The disambiguation code in -// `parseStatement` will already have parsed the init statement or -// expression. - -pp$1.parseFor = function(node, init) { - node.init = init; - this.expect(types.semi); - node.test = this.type === types.semi ? null : this.parseExpression(); - this.expect(types.semi); - node.update = this.type === types.parenR ? null : this.parseExpression(); - this.expect(types.parenR); - this.exitLexicalScope(); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "ForStatement") -}; - -// Parse a `for`/`in` and `for`/`of` loop, which are almost -// same from parser's perspective. - -pp$1.parseForIn = function(node, init) { - var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - if (type == "ForInStatement") { - if (init.type === "AssignmentPattern" || - (init.type === "VariableDeclaration" && init.declarations[0].init != null && - (this.strict || init.declarations[0].id.type !== "Identifier"))) - { this.raise(init.start, "Invalid assignment in for-in loop head"); } - } - node.left = init; - node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); - this.expect(types.parenR); - this.exitLexicalScope(); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, type) -}; - -// Parse a list of variable declarations. - -pp$1.parseVar = function(node, isFor, kind) { - var this$1 = this; - - node.declarations = []; - node.kind = kind; - for (;;) { - var decl = this$1.startNode(); - this$1.parseVarId(decl, kind); - if (this$1.eat(types.eq)) { - decl.init = this$1.parseMaybeAssign(isFor); - } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { - this$1.unexpected(); - } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { - this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); - } else { - decl.init = null; - } - node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); - if (!this$1.eat(types.comma)) { break } - } - return node -}; - -pp$1.parseVarId = function(decl, kind) { - decl.id = this.parseBindingAtom(kind); - this.checkLVal(decl.id, kind, false); -}; - -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { - this.initFunction(node); - if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) - { node.generator = this.eat(types.star); } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - if (isStatement) { - node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent(); - if (node.id) { - this.checkLVal(node.id, "var"); - } - } - - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - this.inGenerator = node.generator; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - this.enterFunctionScope(); - - if (!isStatement) - { node.id = this.type == types.name ? this.parseIdent() : null; } - - this.parseFunctionParams(node); - this.parseFunctionBody(node, allowExpressionBody); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") -}; - -pp$1.parseFunctionParams = function(node) { - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); -}; - -// Parse a class declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseClass = function(node, isStatement) { - var this$1 = this; - - this.next(); - - this.parseClassId(node, isStatement); - this.parseClassSuper(node); - var classBody = this.startNode(); - var hadConstructor = false; - classBody.body = []; - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - var member = this$1.parseClassMember(classBody); - if (member && member.type === "MethodDefinition" && member.kind === "constructor") { - if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); } - hadConstructor = true; - } - } - node.body = this.finishNode(classBody, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") -}; - -pp$1.parseClassMember = function(classBody) { - var this$1 = this; - - if (this.eat(types.semi)) { return null } - - var method = this.startNode(); - var tryContextual = function (k, noLineBreak) { - if ( noLineBreak === void 0 ) noLineBreak = false; - - var start = this$1.start, startLoc = this$1.startLoc; - if (!this$1.eatContextual(k)) { return false } - if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } - if (method.key) { this$1.unexpected(); } - method.computed = false; - method.key = this$1.startNodeAt(start, startLoc); - method.key.name = k; - this$1.finishNode(method.key, "Identifier"); - return false + (typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : factory(global.acorn = {}); +})(undefined, function (exports) { + 'use strict'; + + // Reserved word lists for various dialects of the language + + var reservedWords = { + 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", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" }; - method.kind = "method"; - method.static = tryContextual("static"); - var isGenerator = this.eat(types.star); - var isAsync = false; - if (!isGenerator) { - if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { - isAsync = true; - isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); - } else if (tryContextual("get")) { - method.kind = "get"; - } else if (tryContextual("set")) { - method.kind = "set"; + // And the keywords + + 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"; + + var keywords = { + 5: ecma5AndLessKeywords, + 6: ecma5AndLessKeywords + " const class extends export import super" + }; + + var keywordRelationalOperator = /^in(stanceof)?$/; + + // ## Character categories + + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + // Generated by `bin/generate-identifier-regex.js`. + + 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\u08A0-\u08B4\u08B6-\u08BD\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\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\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\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\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-\u170C\u170E-\u1711\u1720-\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-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\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-\u2C2E\u2C30-\u2C5E\u2C60-\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-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\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-\uAB65\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'; + 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\u08D3-\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\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C04\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\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\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-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\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\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\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\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'; + + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; + + // These are a run-length and offset encoded representation of the + // >0xffff code points that are a valid part of identifiers. The + // offset starts at 0x10000, and each pair of numbers represents an + // offset to the next range, and then a size of the range. They were + // generated by bin/generate-identifier-regex.js + + // eslint-disable-next-line comma-spacing + 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, 157, 310, 10, 21, 11, 7, 153, 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, 477, 28, 11, 0, 9, 21, 190, 52, 76, 44, 33, 24, 27, 35, 30, 0, 12, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 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, 54, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 86, 26, 230, 43, 117, 63, 32, 0, 257, 0, 11, 39, 8, 0, 22, 0, 12, 39, 3, 3, 20, 0, 35, 56, 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, 270, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 68, 12, 0, 67, 12, 65, 1, 31, 6129, 15, 754, 9486, 286, 82, 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, 4149, 196, 60, 67, 1213, 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, 42710, 42, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541]; + + // eslint-disable-next-line comma-spacing + 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, 525, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 4, 9, 83, 11, 7, 0, 161, 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, 280, 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, 19306, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 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, 2214, 6, 110, 6, 6, 9, 792487, 239]; + + // This has a complexity linear to the value of the code. The + // assumption is that looking up astral identifier characters is + // rare. + function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) { + return false; + } + pos += set[i + 1]; + if (pos >= code) { + return true; + } } } - if (!method.key) { this.parsePropertyName(method); } - var key = method.key; - if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || - key.type === "Literal" && key.value === "constructor")) { - if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } - if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } - if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } - method.kind = "constructor"; - } else if (method.static && key.type === "Identifier" && key.name === "prototype") { - this.raise(key.start, "Classes may not have a static property named prototype"); + + // Test whether a given character code starts an identifier. + + function isIdentifierStart(code, astral) { + if (code < 65) { + return code === 36; + } + if (code < 91) { + return true; + } + if (code < 97) { + return code === 95; + } + if (code < 123) { + return true; + } + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + } + if (astral === false) { + return false; + } + return isInAstralSet(code, astralIdentifierStartCodes); } - this.parseClassMethod(classBody, method, isGenerator, isAsync); - if (method.kind === "get" && method.value.params.length !== 0) - { this.raiseRecoverable(method.value.start, "getter should have no params"); } - if (method.kind === "set" && method.value.params.length !== 1) - { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } - if (method.kind === "set" && method.value.params[0].type === "RestElement") - { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } - return method -}; -pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { - method.value = this.parseMethod(isGenerator, isAsync); - classBody.body.push(this.finishNode(method, "MethodDefinition")); -}; + // Test whether a given character is part of an identifier. -pp$1.parseClassId = function(node, isStatement) { - node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; -}; - -pp$1.parseClassSuper = function(node) { - node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; -}; - -// Parses module export declaration. - -pp$1.parseExport = function(node, exports) { - var this$1 = this; - - this.next(); - // export * from '...' - if (this.eat(types.star)) { - this.expectContextual("from"); - if (this.type !== types.string) { this.unexpected(); } - node.source = this.parseExprAtom(); - this.semicolon(); - return this.finishNode(node, "ExportAllDeclaration") + function isIdentifierChar(code, astral) { + if (code < 48) { + return code === 36; + } + if (code < 58) { + return true; + } + if (code < 65) { + return false; + } + if (code < 91) { + return true; + } + if (code < 97) { + return code === 95; + } + if (code < 123) { + return true; + } + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + } + if (astral === false) { + return false; + } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); } - if (this.eat(types._default)) { // export default ... - this.checkExport(exports, "default", this.lastTokStart); - var isAsync; - if (this.type === types._function || (isAsync = this.isAsyncFunction())) { - var fNode = this.startNode(); - this.next(); - if (isAsync) { this.next(); } - node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); - } else if (this.type === types._class) { - var cNode = this.startNode(); - node.declaration = this.parseClass(cNode, "nullableID"); + + // ## Token types + + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. + + // All token type variables start with an underscore, to make them + // easy to recognize. + + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // The `startsExpr` property is used to check if the token ends a + // `yield` expression. It is set on all token types that either can + // directly start an expression (like a quotation mark) or can + // continue an expression (like the body of a string). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var TokenType = function TokenType(label, conf) { + if (conf === void 0) conf = {}; + + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; + }; + + function binop(name, prec) { + return new TokenType(name, { beforeExpr: true, binop: prec }); + } + var beforeExpr = { beforeExpr: true }; + var startsExpr = { startsExpr: true }; + + // Map keyword names to token types. + + var keywords$1 = {}; + + // Succinct definitions of keyword token types + function kw(name, options) { + if (options === void 0) options = {}; + + options.keyword = name; + return keywords$1[name] = new TokenType(name, options); + } + + var types = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + eof: new TokenType("eof"), + + // Punctuation token types. + bracketL: new TokenType("[", { beforeExpr: true, startsExpr: true }), + bracketR: new TokenType("]"), + braceL: new TokenType("{", { beforeExpr: true, startsExpr: true }), + braceR: new TokenType("}"), + parenL: new TokenType("(", { beforeExpr: true, startsExpr: true }), + parenR: new TokenType(")"), + comma: new TokenType(",", beforeExpr), + semi: new TokenType(";", beforeExpr), + colon: new TokenType(":", beforeExpr), + dot: new TokenType("."), + question: new TokenType("?", beforeExpr), + arrow: new TokenType("=>", beforeExpr), + template: new TokenType("template"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", { beforeExpr: true, startsExpr: true }), + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + eq: new TokenType("=", { beforeExpr: true, isAssign: true }), + assign: new TokenType("_=", { beforeExpr: true, isAssign: true }), + incDec: new TokenType("++/--", { prefix: true, postfix: true, startsExpr: true }), + prefix: new TokenType("!/~", { beforeExpr: true, prefix: true, startsExpr: true }), + logicalOR: binop("||", 1), + logicalAND: binop("&&", 2), + bitwiseOR: binop("|", 3), + bitwiseXOR: binop("^", 4), + bitwiseAND: binop("&", 5), + equality: binop("==/!=/===/!==", 6), + relational: binop("/<=/>=", 7), + bitShift: binop("<>/>>>", 8), + plusMin: new TokenType("+/-", { beforeExpr: true, binop: 9, prefix: true, startsExpr: true }), + modulo: binop("%", 10), + star: binop("*", 10), + slash: binop("/", 10), + starstar: new TokenType("**", { beforeExpr: true }), + + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", { isLoop: true, beforeExpr: true }), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", { isLoop: true }), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", { isLoop: true }), + _with: kw("with"), + _new: kw("new", { beforeExpr: true, startsExpr: true }), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import"), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", { beforeExpr: true, binop: 7 }), + _instanceof: kw("instanceof", { beforeExpr: true, binop: 7 }), + _typeof: kw("typeof", { beforeExpr: true, prefix: true, startsExpr: true }), + _void: kw("void", { beforeExpr: true, prefix: true, startsExpr: true }), + _delete: kw("delete", { beforeExpr: true, prefix: true, startsExpr: true }) + }; + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n?|\n|\u2028|\u2029/; + var lineBreakG = new RegExp(lineBreak.source, "g"); + + function isNewLine(code, ecma2019String) { + return code === 10 || code === 13 || !ecma2019String && (code === 0x2028 || code === 0x2029); + } + + var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + + var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + + var ref = Object.prototype; + var hasOwnProperty = ref.hasOwnProperty; + var toString = ref.toString; + + // Checks if an object has a property. + + function has(obj, propName) { + return hasOwnProperty.call(obj, propName); + } + + var isArray = Array.isArray || function (obj) { + return toString.call(obj) === "[object Array]"; + }; + + // These are used when `options.locations` is on, for the + // `startLoc` and `endLoc` properties. + + var Position = function Position(line, col) { + this.line = line; + this.column = col; + }; + + Position.prototype.offset = function offset(n) { + return new Position(this.line, this.column + n); + }; + + var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { + this.source = p.sourceFile; + } + }; + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur; + var match = lineBreakG.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else { + return new Position(line, offset - cur); + } + } + } + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must be + // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10 + // (2019). This influences support for strict mode, the set of + // reserved words, and support for new syntax features. The default + // is 9. + ecmaVersion: 9, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"` or `"module"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called + // when a semicolon is automatically inserted. It will be passed + // th position of the comma as an offset, and if `locations` is + // enabled, it is given the location as a `{line, column}` object + // as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, await identifiers are allowed to appear at the top-level scope, + // but they are still not allowed in non-async functions. + allowAwaitOutsideFunction: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // Interpret and default an options object + + function getOptions(opts) { + var options = {}; + + for (var opt in defaultOptions) { + options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; + } + + if (options.ecmaVersion >= 2015) { + options.ecmaVersion -= 2009; + } + + if (options.allowReserved == null) { + options.allowReserved = options.ecmaVersion < 5; + } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { + return tokens.push(token); + }; + } + if (isArray(options.onComment)) { + options.onComment = pushComment(options, options.onComment); + } + + return options; + } + + function pushComment(options, array) { + return function (block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "Block" : "Line", + value: text, + start: start, + end: end + }; + if (options.locations) { + comment.loc = new SourceLocation(this, startLoc, endLoc); + } + if (options.ranges) { + comment.range = [start, end]; + } + array.push(comment); + }; + } + + // Each scope gets a bitset that may contain these flags + var SCOPE_TOP = 1; + var SCOPE_FUNCTION = 2; + var SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION; + var SCOPE_ASYNC = 4; + var SCOPE_GENERATOR = 8; + var SCOPE_ARROW = 16; + var SCOPE_SIMPLE_CATCH = 32; + var SCOPE_SUPER = 64; + var SCOPE_DIRECT_SUPER = 128; + + function functionFlags(async, generator) { + return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0); + } + + // Used in checkLVal and declareName to determine the type of a binding + var BIND_NONE = 0; + var BIND_VAR = 1; + var BIND_LEXICAL = 2; + var BIND_FUNCTION = 3; + var BIND_SIMPLE_CATCH = 4; + var BIND_OUTSIDE = 5; // Special case for function names as bound inside the function + + function keywordRegexp(words) { + return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$"); + } + + var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); + var reserved = ""; + if (!options.allowReserved) { + for (var v = options.ecmaVersion;; v--) { + if (reserved = reservedWords[v]) { + break; + } + } + if (options.sourceType === "module") { + reserved += " await"; + } + } + this.reservedWords = keywordRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = keywordRegexp(reservedStrict); + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; } else { - node.declaration = this.parseMaybeAssign(); + this.pos = this.lineStart = 0; + this.curLine = 1; + } + + // Properties of the current token: + // Its type + this.type = types.eof; + // For tokens that include more information than their type, the value + this.value = null; + // Its start and end offset + this.start = this.end = this.pos; + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition(); + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext(); + this.exprAllowed = true; + + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; + + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = 0; + // Labels in scope. + this.labels = []; + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") { + this.skipLineComment(2); + } + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterScope(SCOPE_TOP); + + // For RegExp validation + this.regexpState = null; + }; + + var prototypeAccessors = { inFunction: { configurable: true }, inGenerator: { configurable: true }, inAsync: { configurable: true }, allowSuper: { configurable: true }, allowDirectSuper: { configurable: true } }; + + Parser.prototype.parse = function parse() { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node); + }; + + prototypeAccessors.inFunction.get = function () { + return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0; + }; + prototypeAccessors.inGenerator.get = function () { + return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0; + }; + prototypeAccessors.inAsync.get = function () { + return (this.currentVarScope().flags & SCOPE_ASYNC) > 0; + }; + prototypeAccessors.allowSuper.get = function () { + return (this.currentThisScope().flags & SCOPE_SUPER) > 0; + }; + prototypeAccessors.allowDirectSuper.get = function () { + return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0; + }; + + // Switch to a getter for 7.0.0. + Parser.prototype.inNonArrowFunction = function inNonArrowFunction() { + return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0; + }; + + Parser.extend = function extend() { + var plugins = [], + len = arguments.length; + while (len--) { + plugins[len] = arguments[len]; + }var cls = this; + for (var i = 0; i < plugins.length; i++) { + cls = plugins[i](cls); + } + return cls; + }; + + Parser.parse = function parse(input, options) { + return new this(options, input).parse(); + }; + + Parser.parseExpressionAt = function parseExpressionAt(input, pos, options) { + var parser = new this(options, input, pos); + parser.nextToken(); + return parser.parseExpression(); + }; + + Parser.tokenizer = function tokenizer(input, options) { + return new this(options, input); + }; + + Object.defineProperties(Parser.prototype, prototypeAccessors); + + var pp = Parser.prototype; + + // ## Parser utilities + + var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; + pp.strictDirective = function (start) { + var this$1 = this; + + for (;;) { + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this$1.input)[0].length; + var match = literal.exec(this$1.input.slice(start)); + if (!match) { + return false; + } + if ((match[1] || match[2]) === "use strict") { + return true; + } + start += match[0].length; + } + }; + + // Predicate that tests whether the next token is of the given + // type, and if yes, consumes it as a side effect. + + pp.eat = function (type) { + if (this.type === type) { + this.next(); + return true; + } else { + return false; + } + }; + + // Tests whether parsed token is a contextual keyword. + + pp.isContextual = function (name) { + return this.type === types.name && this.value === name && !this.containsEsc; + }; + + // Consumes contextual keyword if possible. + + pp.eatContextual = function (name) { + if (!this.isContextual(name)) { + return false; + } + this.next(); + return true; + }; + + // Asserts that following token is given contextual keyword. + + pp.expectContextual = function (name) { + if (!this.eatContextual(name)) { + this.unexpected(); + } + }; + + // Test whether a semicolon can be inserted at the current position. + + pp.canInsertSemicolon = function () { + return this.type === types.eof || this.type === types.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); + }; + + pp.insertSemicolon = function () { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) { + this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); + } + return true; + } + }; + + // Consume a semicolon, or, failing that, see if we are allowed to + // pretend that there is a semicolon at this position. + + pp.semicolon = function () { + if (!this.eat(types.semi) && !this.insertSemicolon()) { + this.unexpected(); + } + }; + + pp.afterTrailingComma = function (tokType, notNext) { + if (this.type === tokType) { + if (this.options.onTrailingComma) { + this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); + } + if (!notNext) { + this.next(); + } + return true; + } + }; + + // Expect a token of a given type. If found, consume it, otherwise, + // raise an unexpected token error. + + pp.expect = function (type) { + this.eat(type) || this.unexpected(); + }; + + // Raise an unexpected token error. + + pp.unexpected = function (pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); + }; + + function DestructuringErrors() { + this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1; + } + + pp.checkPatternErrors = function (refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { + return; + } + if (refDestructuringErrors.trailingComma > -1) { + this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); + } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { + this.raiseRecoverable(parens, "Parenthesized pattern"); + } + }; + + pp.checkExpressionErrors = function (refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { + return false; + } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { + return shorthandAssign >= 0 || doubleProto >= 0; + } + if (shorthandAssign >= 0) { + this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); + } + if (doubleProto >= 0) { + this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); + } + }; + + pp.checkYieldAwaitInDefaultParams = function () { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) { + this.raise(this.yieldPos, "Yield expression cannot be a default value"); + } + if (this.awaitPos) { + this.raise(this.awaitPos, "Await expression cannot be a default value"); + } + }; + + pp.isSimpleAssignTarget = function (expr) { + if (expr.type === "ParenthesizedExpression") { + return this.isSimpleAssignTarget(expr.expression); + } + return expr.type === "Identifier" || expr.type === "MemberExpression"; + }; + + var pp$1 = Parser.prototype; + + // ### Statement parsing + + // Parse a program. Initializes the parser, reads any number of + // statements, and wraps them in a Program node. Optionally takes a + // `program` argument. If present, the statements will be appended + // to its body instead of creating a new node. + + pp$1.parseTopLevel = function (node) { + var this$1 = this; + + var exports = {}; + if (!node.body) { + node.body = []; + } + while (this.type !== types.eof) { + var stmt = this$1.parseStatement(null, true, exports); + node.body.push(stmt); + } + this.adaptDirectivePrologue(node.body); + this.next(); + if (this.options.ecmaVersion >= 6) { + node.sourceType = this.options.sourceType; + } + return this.finishNode(node, "Program"); + }; + + var loopLabel = { kind: "loop" }; + var switchLabel = { kind: "switch" }; + + pp$1.isLet = function () { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { + return false; + } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, + nextCh = this.input.charCodeAt(next); + if (nextCh === 91 || nextCh === 123) { + return true; + } // '{' and '[' + if (isIdentifierStart(nextCh, true)) { + var pos = next + 1; + while (isIdentifierChar(this.input.charCodeAt(pos), true)) { + ++pos; + } + var ident = this.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) { + return true; + } + } + return false; + }; + + // check 'async [no LineTerminator here] function' + // - 'async /*foo*/ function' is OK. + // - 'async /*\n*/ function' is invalid. + pp$1.isAsyncFunction = function () { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) { + return false; + } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + return !lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))); + }; + + // Parse a single statement. + // + // If expecting a statement and finding a slash operator, parse a + // regular expression literal. This is to handle cases like + // `if (foo) /blah/.exec(foo)`, where looking at the previous token + // does not help. + + pp$1.parseStatement = function (context, topLevel, exports) { + var starttype = this.type, + node = this.startNode(), + kind; + + if (this.isLet()) { + starttype = types._var; + kind = "let"; + } + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case types._break:case types._continue: + return this.parseBreakContinueStatement(node, starttype.keyword); + case types._debugger: + return this.parseDebuggerStatement(node); + case types._do: + return this.parseDoStatement(node); + case types._for: + return this.parseForStatement(node); + case types._function: + if (context && (this.strict || context !== "if") && this.options.ecmaVersion >= 6) { + this.unexpected(); + } + return this.parseFunctionStatement(node, false, !context); + case types._class: + if (context) { + this.unexpected(); + } + return this.parseClass(node, true); + case types._if: + return this.parseIfStatement(node); + case types._return: + return this.parseReturnStatement(node); + case types._switch: + return this.parseSwitchStatement(node); + case types._throw: + return this.parseThrowStatement(node); + case types._try: + return this.parseTryStatement(node); + case types._const:case types._var: + kind = kind || this.value; + if (context && kind !== "var") { + this.unexpected(); + } + return this.parseVarStatement(node, kind); + case types._while: + return this.parseWhileStatement(node); + case types._with: + return this.parseWithStatement(node); + case types.braceL: + return this.parseBlock(true, node); + case types.semi: + return this.parseEmptyStatement(node); + case types._export: + case types._import: + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) { + this.raise(this.start, "'import' and 'export' may only appear at the top level"); + } + if (!this.inModule) { + this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); + } + } + return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports); + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + if (this.isAsyncFunction()) { + if (context) { + this.unexpected(); + } + this.next(); + return this.parseFunctionStatement(node, true, !context); + } + + var maybeName = this.value, + expr = this.parseExpression(); + if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) { + return this.parseLabeledStatement(node, maybeName, expr, context); + } else { + return this.parseExpressionStatement(node, expr); + } + } + }; + + pp$1.parseBreakContinueStatement = function (node, keyword) { + var this$1 = this; + + var isBreak = keyword === "break"; + this.next(); + if (this.eat(types.semi) || this.insertSemicolon()) { + node.label = null; + } else if (this.type !== types.name) { + this.unexpected(); + } else { + node.label = this.parseIdent(); this.semicolon(); } - return this.finishNode(node, "ExportDefaultDeclaration") - } - // export var|const|let|function|class ... - if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(true); - if (node.declaration.type === "VariableDeclaration") - { this.checkVariableExport(exports, node.declaration.declarations); } - else - { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } - node.specifiers = []; - node.source = null; - } else { // export { x, y as z } [from '...'] - node.declaration = null; - node.specifiers = this.parseExportSpecifiers(exports); - if (this.eatContextual("from")) { - if (this.type !== types.string) { this.unexpected(); } - node.source = this.parseExprAtom(); - } else { - // check for keywords used as local names - for (var i = 0, list = node.specifiers; i < list.length; i += 1) { - var spec = list[i]; - this$1.checkUnreserved(spec.local); + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this$1.labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) { + break; + } + if (node.label && isBreak) { + break; + } } - - node.source = null; } + if (i === this.labels.length) { + this.raise(node.start, "Unsyntactic " + keyword); + } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); + }; + + pp$1.parseDebuggerStatement = function (node) { + this.next(); this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration") -}; + return this.finishNode(node, "DebuggerStatement"); + }; -pp$1.checkExport = function(exports, name, pos) { - if (!exports) { return } - if (has(exports, name)) - { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } - exports[name] = true; -}; + pp$1.parseDoStatement = function (node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement("do"); + this.labels.pop(); + this.expect(types._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) { + this.eat(types.semi); + } else { + this.semicolon(); + } + return this.finishNode(node, "DoWhileStatement"); + }; -pp$1.checkPatternExport = function(exports, pat) { - var this$1 = this; + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` + // loop is non-trivial. Basically, we have to parse the init `var` + // statement or expression, disallowing the `in` operator (see + // the second parameter to `parseExpression`), and then check + // whether the next token is `in` or `of`. When there is no init + // part (semicolon immediately after the opening parenthesis), it + // is a regular `for` loop. - var type = pat.type; - if (type == "Identifier") - { this.checkExport(exports, pat.name, pat.start); } - else if (type == "ObjectPattern") - { for (var i = 0, list = pat.properties; i < list.length; i += 1) - { + pp$1.parseForStatement = function (node) { + this.next(); + var awaitAt = this.options.ecmaVersion >= 9 && (this.inAsync || !this.inFunction && this.options.allowAwaitOutsideFunction) && this.eatContextual("await") ? this.lastTokStart : -1; + this.labels.push(loopLabel); + this.enterScope(0); + this.expect(types.parenL); + if (this.type === types.semi) { + if (awaitAt > -1) { + this.unexpected(awaitAt); + } + return this.parseFor(node, null); + } + var isLet = this.isLet(); + if (this.type === types._var || this.type === types._const || isLet) { + var init$1 = this.startNode(), + kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + if ((this.type === types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && init$1.declarations.length === 1 && !(kind !== "var" && init$1.declarations[0].init)) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { + this.unexpected(awaitAt); + } + } else { + node.await = awaitAt > -1; + } + } + return this.parseForIn(node, init$1); + } + if (awaitAt > -1) { + this.unexpected(awaitAt); + } + return this.parseFor(node, init$1); + } + var refDestructuringErrors = new DestructuringErrors(); + var init = this.parseExpression(true, refDestructuringErrors); + if (this.type === types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { + this.unexpected(awaitAt); + } + } else { + node.await = awaitAt > -1; + } + } + this.toAssignable(init, false, refDestructuringErrors); + this.checkLVal(init); + return this.parseForIn(node, init); + } else { + this.checkExpressionErrors(refDestructuringErrors, true); + } + if (awaitAt > -1) { + this.unexpected(awaitAt); + } + return this.parseFor(node, init); + }; + + pp$1.parseFunctionStatement = function (node, isAsync, declarationPosition) { + this.next(); + return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync); + }; + + pp$1.parseIfStatement = function (node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement("if"); + node.alternate = this.eat(types._else) ? this.parseStatement("if") : null; + return this.finishNode(node, "IfStatement"); + }; + + pp$1.parseReturnStatement = function (node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) { + this.raise(this.start, "'return' outside of function"); + } + this.next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(types.semi) || this.insertSemicolon()) { + node.argument = null; + } else { + node.argument = this.parseExpression();this.semicolon(); + } + return this.finishNode(node, "ReturnStatement"); + }; + + pp$1.parseSwitchStatement = function (node) { + var this$1 = this; + + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types.braceL); + this.labels.push(switchLabel); + this.enterScope(0); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type !== types.braceR;) { + if (this$1.type === types._case || this$1.type === types._default) { + var isCase = this$1.type === types._case; + if (cur) { + this$1.finishNode(cur, "SwitchCase"); + } + node.cases.push(cur = this$1.startNode()); + cur.consequent = []; + this$1.next(); + if (isCase) { + cur.test = this$1.parseExpression(); + } else { + if (sawDefault) { + this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); + } + sawDefault = true; + cur.test = null; + } + this$1.expect(types.colon); + } else { + if (!cur) { + this$1.unexpected(); + } + cur.consequent.push(this$1.parseStatement(null)); + } + } + this.exitScope(); + if (cur) { + this.finishNode(cur, "SwitchCase"); + } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement"); + }; + + pp$1.parseThrowStatement = function (node) { + this.next(); + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) { + this.raise(this.lastTokEnd, "Illegal newline after throw"); + } + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement"); + }; + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + pp$1.parseTryStatement = function (node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(types.parenL)) { + clause.param = this.parseBindingAtom(); + var simple = clause.param.type === "Identifier"; + this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); + this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); + this.expect(types.parenR); + } else { + if (this.options.ecmaVersion < 10) { + this.unexpected(); + } + clause.param = null; + this.enterScope(0); + } + clause.body = this.parseBlock(false); + this.exitScope(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) { + this.raise(node.start, "Missing catch or finally clause"); + } + return this.finishNode(node, "TryStatement"); + }; + + pp$1.parseVarStatement = function (node, kind) { + this.next(); + this.parseVar(node, false, kind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration"); + }; + + pp$1.parseWhileStatement = function (node) { + this.next(); + node.test = this.parseParenExpression(); + this.labels.push(loopLabel); + node.body = this.parseStatement("while"); + this.labels.pop(); + return this.finishNode(node, "WhileStatement"); + }; + + pp$1.parseWithStatement = function (node) { + if (this.strict) { + this.raise(this.start, "'with' in strict mode"); + } + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement("with"); + return this.finishNode(node, "WithStatement"); + }; + + pp$1.parseEmptyStatement = function (node) { + this.next(); + return this.finishNode(node, "EmptyStatement"); + }; + + pp$1.parseLabeledStatement = function (node, maybeName, expr, context) { + var this$1 = this; + + for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) { + var label = list[i$1]; + + if (label.name === maybeName) { + this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } + } + var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this$1.labels[i]; + if (label$1.statementStart === node.start) { + // Update information about previous labels on this node + label$1.statementStart = this$1.start; + label$1.kind = kind; + } else { + break; + } + } + this.labels.push({ name: maybeName, kind: kind, statementStart: this.start }); + node.body = this.parseStatement(context); + if (node.body.type === "ClassDeclaration" || node.body.type === "VariableDeclaration" && node.body.kind !== "var" || node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator || node.body.async)) { + this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); + } + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement"); + }; + + pp$1.parseExpressionStatement = function (node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement"); + }; + + // Parse a semicolon-enclosed block of statements, handling `"use + // strict"` declarations when `allowStrict` is true (used for + // function bodies). + + pp$1.parseBlock = function (createNewLexicalScope, node) { + var this$1 = this; + if (createNewLexicalScope === void 0) createNewLexicalScope = true; + if (node === void 0) node = this.startNode(); + + node.body = []; + this.expect(types.braceL); + if (createNewLexicalScope) { + this.enterScope(0); + } + while (!this.eat(types.braceR)) { + var stmt = this$1.parseStatement(null); + node.body.push(stmt); + } + if (createNewLexicalScope) { + this.exitScope(); + } + return this.finishNode(node, "BlockStatement"); + }; + + // Parse a regular `for` loop. The disambiguation code in + // `parseStatement` will already have parsed the init statement or + // expression. + + pp$1.parseFor = function (node, init) { + node.init = init; + this.expect(types.semi); + node.test = this.type === types.semi ? null : this.parseExpression(); + this.expect(types.semi); + node.update = this.type === types.parenR ? null : this.parseExpression(); + this.expect(types.parenR); + this.exitScope(); + node.body = this.parseStatement("for"); + this.labels.pop(); + return this.finishNode(node, "ForStatement"); + }; + + // Parse a `for`/`in` and `for`/`of` loop, which are almost + // same from parser's perspective. + + pp$1.parseForIn = function (node, init) { + var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; + this.next(); + if (type === "ForInStatement") { + if (init.type === "AssignmentPattern" || init.type === "VariableDeclaration" && init.declarations[0].init != null && (this.strict || init.declarations[0].id.type !== "Identifier")) { + this.raise(init.start, "Invalid assignment in for-in loop head"); + } + } + node.left = init; + node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types.parenR); + this.exitScope(); + node.body = this.parseStatement("for"); + this.labels.pop(); + return this.finishNode(node, type); + }; + + // Parse a list of variable declarations. + + pp$1.parseVar = function (node, isFor, kind) { + var this$1 = this; + + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this$1.startNode(); + this$1.parseVarId(decl, kind); + if (this$1.eat(types.eq)) { + decl.init = this$1.parseMaybeAssign(isFor); + } else if (kind === "const" && !(this$1.type === types._in || this$1.options.ecmaVersion >= 6 && this$1.isContextual("of"))) { + this$1.unexpected(); + } else if (decl.id.type !== "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { + this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); + if (!this$1.eat(types.comma)) { + break; + } + } + return node; + }; + + pp$1.parseVarId = function (decl, kind) { + decl.id = this.parseBindingAtom(kind); + this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); + }; + + var FUNC_STATEMENT = 1; + var FUNC_HANGING_STATEMENT = 2; + var FUNC_NULLABLE_ID = 4; + + // Parse a function declaration or literal (depending on the + // `isStatement` parameter). + + pp$1.parseFunction = function (node, statement, allowExpressionBody, isAsync) { + this.initFunction(node); + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { + node.generator = this.eat(types.star); + } + if (this.options.ecmaVersion >= 8) { + node.async = !!isAsync; + } + + if (statement & FUNC_STATEMENT) { + node.id = statement & FUNC_NULLABLE_ID && this.type !== types.name ? null : this.parseIdent(); + if (node.id && !(statement & FUNC_HANGING_STATEMENT)) { + this.checkLVal(node.id, this.inModule && !this.inFunction ? BIND_LEXICAL : BIND_FUNCTION); + } + } + + var oldYieldPos = this.yieldPos, + oldAwaitPos = this.awaitPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.enterScope(functionFlags(node.async, node.generator)); + + if (!(statement & FUNC_STATEMENT)) { + node.id = this.type === types.name ? this.parseIdent() : null; + } + + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.finishNode(node, statement & FUNC_STATEMENT ? "FunctionDeclaration" : "FunctionExpression"); + }; + + pp$1.parseFunctionParams = function (node) { + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + }; + + // Parse a class declaration or literal (depending on the + // `isStatement` parameter). + + pp$1.parseClass = function (node, isStatement) { + var this$1 = this; + + this.next(); + + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + var element = this$1.parseClassElement(node.superClass !== null); + if (element) { + classBody.body.push(element); + if (element.type === "MethodDefinition" && element.kind === "constructor") { + if (hadConstructor) { + this$1.raise(element.start, "Duplicate constructor in the same class"); + } + hadConstructor = true; + } + } + } + node.body = this.finishNode(classBody, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); + }; + + pp$1.parseClassElement = function (constructorAllowsSuper) { + var this$1 = this; + + if (this.eat(types.semi)) { + return null; + } + + var method = this.startNode(); + var tryContextual = function tryContextual(k, noLineBreak) { + if (noLineBreak === void 0) noLineBreak = false; + + var start = this$1.start, + startLoc = this$1.startLoc; + if (!this$1.eatContextual(k)) { + return false; + } + if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { + return true; + } + if (method.key) { + this$1.unexpected(); + } + method.computed = false; + method.key = this$1.startNodeAt(start, startLoc); + method.key.name = k; + this$1.finishNode(method.key, "Identifier"); + return false; + }; + + method.kind = "method"; + method.static = tryContextual("static"); + var isGenerator = this.eat(types.star); + var isAsync = false; + if (!isGenerator) { + if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + } else if (tryContextual("get")) { + method.kind = "get"; + } else if (tryContextual("set")) { + method.kind = "set"; + } + } + if (!method.key) { + this.parsePropertyName(method); + } + var key = method.key; + var allowsDirectSuper = false; + if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { + if (method.kind !== "method") { + this.raise(key.start, "Constructor can't have get/set modifier"); + } + if (isGenerator) { + this.raise(key.start, "Constructor can't be a generator"); + } + if (isAsync) { + this.raise(key.start, "Constructor can't be an async method"); + } + method.kind = "constructor"; + allowsDirectSuper = constructorAllowsSuper; + } else if (method.static && key.type === "Identifier" && key.name === "prototype") { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper); + if (method.kind === "get" && method.value.params.length !== 0) { + this.raiseRecoverable(method.value.start, "getter should have no params"); + } + if (method.kind === "set" && method.value.params.length !== 1) { + this.raiseRecoverable(method.value.start, "setter should have exactly one param"); + } + if (method.kind === "set" && method.value.params[0].type === "RestElement") { + this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); + } + return method; + }; + + pp$1.parseClassMethod = function (method, isGenerator, isAsync, allowsDirectSuper) { + method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); + return this.finishNode(method, "MethodDefinition"); + }; + + pp$1.parseClassId = function (node, isStatement) { + node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; + }; + + pp$1.parseClassSuper = function (node) { + node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; + }; + + // Parses module export declaration. + + pp$1.parseExport = function (node, exports) { + var this$1 = this; + + this.next(); + // export * from '...' + if (this.eat(types.star)) { + this.expectContextual("from"); + if (this.type !== types.string) { + this.unexpected(); + } + node.source = this.parseExprAtom(); + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration"); + } + if (this.eat(types._default)) { + // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === types._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { + this.next(); + } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync, true); + } else if (this.type === types._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration"); + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") { + this.checkVariableExport(exports, node.declaration.declarations); + } else { + this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); + } + node.specifiers = []; + node.source = null; + } else { + // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types.string) { + this.unexpected(); + } + node.source = this.parseExprAtom(); + } else { + // check for keywords used as local names + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + var spec = list[i]; + + this$1.checkUnreserved(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration"); + }; + + pp$1.checkExport = function (exports, name, pos) { + if (!exports) { + return; + } + if (has(exports, name)) { + this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); + } + exports[name] = true; + }; + + pp$1.checkPatternExport = function (exports, pat) { + var this$1 = this; + + var type = pat.type; + if (type === "Identifier") { + this.checkExport(exports, pat.name, pat.start); + } else if (type === "ObjectPattern") { + for (var i = 0, list = pat.properties; i < list.length; i += 1) { var prop = list[i]; this$1.checkPatternExport(exports, prop); - } } - else if (type == "ArrayPattern") - { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { - var elt = list$1[i$1]; + } + } else if (type === "ArrayPattern") { + for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; - if (elt) { this$1.checkPatternExport(exports, elt); } - } } - else if (type == "Property") - { this.checkPatternExport(exports, pat.value); } - else if (type == "AssignmentPattern") - { this.checkPatternExport(exports, pat.left); } - else if (type == "RestElement") - { this.checkPatternExport(exports, pat.argument); } - else if (type == "ParenthesizedExpression") - { this.checkPatternExport(exports, pat.expression); } -}; - -pp$1.checkVariableExport = function(exports, decls) { - var this$1 = this; - - if (!exports) { return } - for (var i = 0, list = decls; i < list.length; i += 1) - { - var decl = list[i]; - - this$1.checkPatternExport(exports, decl.id); - } -}; - -pp$1.shouldParseExportStatement = function() { - return this.type.keyword === "var" || - this.type.keyword === "const" || - this.type.keyword === "class" || - this.type.keyword === "function" || - this.isLet() || - this.isAsyncFunction() -}; - -// Parses a comma-separated list of module exports. - -pp$1.parseExportSpecifiers = function(exports) { - var this$1 = this; - - var nodes = [], first = true; - // export { x, y as z } [from '...'] - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node = this$1.startNode(); - node.local = this$1.parseIdent(true); - node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; - this$1.checkExport(exports, node.exported.name, node.exported.start); - nodes.push(this$1.finishNode(node, "ExportSpecifier")); - } - return nodes -}; - -// Parses import declaration. - -pp$1.parseImport = function(node) { - this.next(); - // import '...' - if (this.type === types.string) { - node.specifiers = empty; - node.source = this.parseExprAtom(); - } else { - node.specifiers = this.parseImportSpecifiers(); - this.expectContextual("from"); - node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration") -}; - -// Parses a comma-separated list of module imports. - -pp$1.parseImportSpecifiers = function() { - var this$1 = this; - - var nodes = [], first = true; - if (this.type === types.name) { - // import defaultObj, { x, y as z } from '...' - var node = this.startNode(); - node.local = this.parseIdent(); - this.checkLVal(node.local, "let"); - nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); - if (!this.eat(types.comma)) { return nodes } - } - if (this.type === types.star) { - var node$1 = this.startNode(); - this.next(); - this.expectContextual("as"); - node$1.local = this.parseIdent(); - this.checkLVal(node$1.local, "let"); - nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); - return nodes - } - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node$2 = this$1.startNode(); - node$2.imported = this$1.parseIdent(true); - if (this$1.eatContextual("as")) { - node$2.local = this$1.parseIdent(); - } else { - this$1.checkUnreserved(node$2.imported); - node$2.local = node$2.imported; - } - this$1.checkLVal(node$2.local, "let"); - nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); - } - return nodes -}; - -// Set `ExpressionStatement#directive` property for directive prologues. -pp$1.adaptDirectivePrologue = function(statements) { - for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { - statements[i].directive = statements[i].expression.raw.slice(1, -1); - } -}; -pp$1.isDirectiveCandidate = function(statement) { - return ( - statement.type === "ExpressionStatement" && - statement.expression.type === "Literal" && - typeof statement.expression.value === "string" && - // Reject parenthesized strings. - (this.input[statement.start] === "\"" || this.input[statement.start] === "'") - ) -}; - -var pp$2 = Parser.prototype; - -// Convert existing expression atom to assignable pattern -// if possible. - -pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { - var this$1 = this; - - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { - case "Identifier": - if (this.inAsync && node.name === "await") - { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } - break - - case "ObjectPattern": - case "ArrayPattern": - case "RestElement": - break - - case "ObjectExpression": - node.type = "ObjectPattern"; - if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - for (var i = 0, list = node.properties; i < list.length; i += 1) { - var prop = list[i]; - - this$1.toAssignable(prop, isBinding); - // Early error: - // AssignmentRestProperty[Yield, Await] : - // `...` DestructuringAssignmentTarget[Yield, Await] - // - // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. - if ( - prop.type === "RestElement" && - (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") - ) { - this$1.raise(prop.argument.start, "Unexpected token"); + if (elt) { + this$1.checkPatternExport(exports, elt); } } - break - - case "Property": - // AssignmentProperty has type == "Property" - if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } - this.toAssignable(node.value, isBinding); - break - - case "ArrayExpression": - node.type = "ArrayPattern"; - if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - this.toAssignableList(node.elements, isBinding); - break - - case "SpreadElement": - node.type = "RestElement"; - this.toAssignable(node.argument, isBinding); - if (node.argument.type === "AssignmentPattern") - { this.raise(node.argument.start, "Rest elements cannot have a default value"); } - break - - case "AssignmentExpression": - if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } - node.type = "AssignmentPattern"; - delete node.operator; - this.toAssignable(node.left, isBinding); - // falls through to AssignmentPattern - - case "AssignmentPattern": - break - - case "ParenthesizedExpression": - this.toAssignable(node.expression, isBinding); - break - - case "MemberExpression": - if (!isBinding) { break } - - default: - this.raise(node.start, "Assigning to rvalue"); + } else if (type === "Property") { + this.checkPatternExport(exports, pat.value); + } else if (type === "AssignmentPattern") { + this.checkPatternExport(exports, pat.left); + } else if (type === "RestElement") { + this.checkPatternExport(exports, pat.argument); + } else if (type === "ParenthesizedExpression") { + this.checkPatternExport(exports, pat.expression); } - } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - return node -}; + }; -// Convert list of expression atoms to binding list. - -pp$2.toAssignableList = function(exprList, isBinding) { - var this$1 = this; - - var end = exprList.length; - for (var i = 0; i < end; i++) { - var elt = exprList[i]; - if (elt) { this$1.toAssignable(elt, isBinding); } - } - if (end) { - var last = exprList[end - 1]; - if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") - { this.unexpected(last.argument.start); } - } - return exprList -}; - -// Parses spread element. - -pp$2.parseSpread = function(refDestructuringErrors) { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeAssign(false, refDestructuringErrors); - return this.finishNode(node, "SpreadElement") -}; - -pp$2.parseRestBinding = function() { - var node = this.startNode(); - this.next(); - - // RestElement inside of a function parameter must be an identifier - if (this.options.ecmaVersion === 6 && this.type !== types.name) - { this.unexpected(); } - - node.argument = this.parseBindingAtom(); - - return this.finishNode(node, "RestElement") -}; - -// Parses lvalue (assignable) atom. - -pp$2.parseBindingAtom = function() { - if (this.options.ecmaVersion >= 6) { - switch (this.type) { - case types.bracketL: - var node = this.startNode(); - this.next(); - node.elements = this.parseBindingList(types.bracketR, true, true); - return this.finishNode(node, "ArrayPattern") - - case types.braceL: - return this.parseObj(true) - } - } - return this.parseIdent() -}; - -pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (first) { first = false; } - else { this$1.expect(types.comma); } - if (allowEmpty && this$1.type === types.comma) { - elts.push(null); - } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { - break - } else if (this$1.type === types.ellipsis) { - var rest = this$1.parseRestBinding(); - this$1.parseBindingListItem(rest); - elts.push(rest); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - this$1.expect(close); - break - } else { - var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); - this$1.parseBindingListItem(elem); - elts.push(elem); - } - } - return elts -}; - -pp$2.parseBindingListItem = function(param) { - return param -}; - -// Parses assignment pattern around given atom if possible. - -pp$2.parseMaybeDefault = function(startPos, startLoc, left) { - left = left || this.parseBindingAtom(); - if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.right = this.parseMaybeAssign(); - return this.finishNode(node, "AssignmentPattern") -}; - -// Verify that a node is an lval — something that can be assigned -// to. -// bindingType can be either: -// 'var' indicating that the lval creates a 'var' binding -// 'let' indicating that the lval creates a lexical ('let' or 'const') binding -// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references - -pp$2.checkLVal = function(expr, bindingType, checkClashes) { - var this$1 = this; - - switch (expr.type) { - case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } - if (checkClashes) { - if (has(checkClashes, expr.name)) - { this.raiseRecoverable(expr.start, "Argument name clash"); } - checkClashes[expr.name] = true; - } - if (bindingType && bindingType !== "none") { - if ( - bindingType === "var" && !this.canDeclareVarName(expr.name) || - bindingType !== "var" && !this.canDeclareLexicalName(expr.name) - ) { - this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); - } - if (bindingType === "var") { - this.declareVarName(expr.name); - } else { - this.declareLexicalName(expr.name); - } - } - break - - case "MemberExpression": - if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } - break - - case "ObjectPattern": - for (var i = 0, list = expr.properties; i < list.length; i += 1) - { - var prop = list[i]; - - this$1.checkLVal(prop, bindingType, checkClashes); - } - break - - case "Property": - // AssignmentProperty has type == "Property" - this.checkLVal(expr.value, bindingType, checkClashes); - break - - case "ArrayPattern": - for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { - var elem = list$1[i$1]; - - if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } - } - break - - case "AssignmentPattern": - this.checkLVal(expr.left, bindingType, checkClashes); - break - - case "RestElement": - this.checkLVal(expr.argument, bindingType, checkClashes); - break - - case "ParenthesizedExpression": - this.checkLVal(expr.expression, bindingType, checkClashes); - break - - default: - this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); - } -}; - -// A recursive descent parser operates by defining functions for all -// syntactic elements, and recursively calling those, each function -// advancing the input stream and returning an AST node. Precedence -// of constructs (for example, the fact that `!x[1]` means `!(x[1])` -// instead of `(!x)[1]` is handled by the fact that the parser -// function that parses unary prefix operators is called first, and -// in turn calls the function that parses `[]` subscripts — that -// way, it'll receive the node for `x[1]` already parsed, and wraps -// *that* in the unary operator node. -// -// Acorn uses an [operator precedence parser][opp] to handle binary -// operator precedence, because it is much more compact than using -// the technique outlined above, which uses different, nesting -// functions to specify precedence, for all of the ten binary -// precedence levels that JavaScript defines. -// -// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser - -var pp$3 = Parser.prototype; - -// Check if property name clashes with already added. -// Object/class getters and setters are not allowed to clash — -// either with each other or with an init property — and in -// strict mode, init properties are also not allowed to be repeated. - -pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { - if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") - { return } - if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) - { return } - var key = prop.key; - var name; - switch (key.type) { - case "Identifier": name = key.name; break - case "Literal": name = String(key.value); break - default: return - } - var kind = prop.kind; - if (this.options.ecmaVersion >= 6) { - if (name === "__proto__" && kind === "init") { - if (propHash.proto) { - if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } - // Backwards-compat kludge. Can be removed in version 6.0 - else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } - } - propHash.proto = true; - } - return - } - name = "$" + name; - var other = propHash[name]; - if (other) { - var redefinition; - if (kind === "init") { - redefinition = this.strict && other.init || other.get || other.set; - } else { - redefinition = other.init || other[kind]; - } - if (redefinition) - { this.raiseRecoverable(key.start, "Redefinition of property"); } - } else { - other = propHash[name] = { - init: false, - get: false, - set: false - }; - } - other[kind] = true; -}; - -// ### Expression parsing - -// These nest, from the most general expression type at the top to -// 'atomic', nondivisible expression types at the bottom. Most of -// the functions will simply let the function(s) below them parse, -// and, *if* the syntactic construct they handle is present, wrap -// the AST node that the inner parser gave them in another node. - -// Parse a full expression. The optional arguments are used to -// forbid the `in` operator (in for loops initalization expressions) -// and provide reference for storing '=' operator inside shorthand -// property assignment in contexts where both object expression -// and object pattern might appear (so it's possible to raise -// delayed syntax error at correct position). - -pp$3.parseExpression = function(noIn, refDestructuringErrors) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); - if (this.type === types.comma) { - var node = this.startNodeAt(startPos, startLoc); - node.expressions = [expr]; - while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } - return this.finishNode(node, "SequenceExpression") - } - return expr -}; - -// Parse an assignment expression. This includes applications of -// operators like `+=`. - -pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { - if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } - - var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; - if (refDestructuringErrors) { - oldParenAssign = refDestructuringErrors.parenthesizedAssign; - oldTrailingComma = refDestructuringErrors.trailingComma; - refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; - } else { - refDestructuringErrors = new DestructuringErrors; - ownDestructuringErrors = true; - } - - var startPos = this.start, startLoc = this.startLoc; - if (this.type == types.parenL || this.type == types.name) - { this.potentialArrowAt = this.start; } - var left = this.parseMaybeConditional(noIn, refDestructuringErrors); - if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } - if (this.type.isAssign) { - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; - if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } - refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly - this.checkLVal(left); - this.next(); - node.right = this.parseMaybeAssign(noIn); - return this.finishNode(node, "AssignmentExpression") - } else { - if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } - } - if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } - if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } - return left -}; - -// Parse a ternary conditional (`?:`) operator. - -pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - if (this.eat(types.question)) { - var node = this.startNodeAt(startPos, startLoc); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - this.expect(types.colon); - node.alternate = this.parseMaybeAssign(noIn); - return this.finishNode(node, "ConditionalExpression") - } - return expr -}; - -// Start the precedence parser. - -pp$3.parseExprOps = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refDestructuringErrors, false); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) -}; - -// Parse binary operators with the operator precedence parsing -// algorithm. `left` is the left-hand side of the operator. -// `minPrec` provides context that allows the function to stop and -// defer further parser to one of its callers when it encounters an -// operator that has a lower precedence than the set it is parsing. - -pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { - var prec = this.type.binop; - if (prec != null && (!noIn || this.type !== types._in)) { - if (prec > minPrec) { - var logical = this.type === types.logicalOR || this.type === types.logicalAND; - var op = this.value; - this.next(); - var startPos = this.start, startLoc = this.startLoc; - var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); - var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); - return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) - } - } - return left -}; - -pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.operator = op; - node.right = right; - return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") -}; - -// Parse unary operators, both prefix and postfix. - -pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, expr; - if (this.inAsync && this.isContextual("await")) { - expr = this.parseAwait(); - sawUnary = true; - } else if (this.type.prefix) { - var node = this.startNode(), update = this.type === types.incDec; - node.operator = this.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(null, true); - this.checkExpressionErrors(refDestructuringErrors, true); - if (update) { this.checkLVal(node.argument); } - else if (this.strict && node.operator === "delete" && - node.argument.type === "Identifier") - { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } - else { sawUnary = true; } - expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } else { - expr = this.parseExprSubscripts(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - while (this.type.postfix && !this.canInsertSemicolon()) { - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.operator = this$1.value; - node$1.prefix = false; - node$1.argument = expr; - this$1.checkLVal(expr); - this$1.next(); - expr = this$1.finishNode(node$1, "UpdateExpression"); - } - } - - if (!sawUnary && this.eat(types.starstar)) - { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } - else - { return expr } -}; - -// Parse call, dot, and `[]`-subscript expressions. - -pp$3.parseExprSubscripts = function(refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprAtom(refDestructuringErrors); - var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; - if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } - var result = this.parseSubscripts(expr, startPos, startLoc); - if (refDestructuringErrors && result.type === "MemberExpression") { - if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } - if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } - } - return result -}; - -pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { - var this$1 = this; - - var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && - this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; - for (var computed = (void 0);;) { - if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { - var node = this$1.startNodeAt(startPos, startLoc); - node.object = base; - node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); - node.computed = !!computed; - if (computed) { this$1.expect(types.bracketR); } - base = this$1.finishNode(node, "MemberExpression"); - } else if (!noCalls && this$1.eat(types.parenL)) { - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; - this$1.yieldPos = 0; - this$1.awaitPos = 0; - var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); - if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { - this$1.checkPatternErrors(refDestructuringErrors, false); - this$1.checkYieldAwaitInDefaultParams(); - this$1.yieldPos = oldYieldPos; - this$1.awaitPos = oldAwaitPos; - return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) - } - this$1.checkExpressionErrors(refDestructuringErrors, true); - this$1.yieldPos = oldYieldPos || this$1.yieldPos; - this$1.awaitPos = oldAwaitPos || this$1.awaitPos; - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.callee = base; - node$1.arguments = exprList; - base = this$1.finishNode(node$1, "CallExpression"); - } else if (this$1.type === types.backQuote) { - var node$2 = this$1.startNodeAt(startPos, startLoc); - node$2.tag = base; - node$2.quasi = this$1.parseTemplate({isTagged: true}); - base = this$1.finishNode(node$2, "TaggedTemplateExpression"); - } else { - return base - } - } -}; - -// Parse an atomic expression — either a single token that is an -// expression, an expression started by a keyword like `function` or -// `new`, or an expression wrapped in punctuation like `()`, `[]`, -// or `{}`. - -pp$3.parseExprAtom = function(refDestructuringErrors) { - var node, canBeArrow = this.potentialArrowAt == this.start; - switch (this.type) { - case types._super: - if (!this.inFunction) - { this.raise(this.start, "'super' outside of function or class"); } - node = this.startNode(); - this.next(); - // The `super` keyword can appear at below: - // SuperProperty: - // super [ Expression ] - // super . IdentifierName - // SuperCall: - // super Arguments - if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) - { this.unexpected(); } - return this.finishNode(node, "Super") - - case types._this: - node = this.startNode(); - this.next(); - return this.finishNode(node, "ThisExpression") - - case types.name: - var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; - var id = this.parseIdent(this.type !== types.name); - if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) - { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } - if (canBeArrow && !this.canInsertSemicolon()) { - if (this.eat(types.arrow)) - { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } - if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { - id = this.parseIdent(); - if (this.canInsertSemicolon() || !this.eat(types.arrow)) - { this.unexpected(); } - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) - } - } - return id - - case types.regexp: - var value = this.value; - node = this.parseLiteral(value.value); - node.regex = {pattern: value.pattern, flags: value.flags}; - return node - - case types.num: case types.string: - return this.parseLiteral(this.value) - - case types._null: case types._true: case types._false: - node = this.startNode(); - node.value = this.type === types._null ? null : this.type === types._true; - node.raw = this.type.keyword; - this.next(); - return this.finishNode(node, "Literal") - - case types.parenL: - var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); - if (refDestructuringErrors) { - if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) - { refDestructuringErrors.parenthesizedAssign = start; } - if (refDestructuringErrors.parenthesizedBind < 0) - { refDestructuringErrors.parenthesizedBind = start; } - } - return expr - - case types.bracketL: - node = this.startNode(); - this.next(); - node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); - return this.finishNode(node, "ArrayExpression") - - case types.braceL: - return this.parseObj(false, refDestructuringErrors) - - case types._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false) - - case types._class: - return this.parseClass(this.startNode(), false) - - case types._new: - return this.parseNew() - - case types.backQuote: - return this.parseTemplate() - - default: - this.unexpected(); - } -}; - -pp$3.parseLiteral = function(value) { - var node = this.startNode(); - node.value = value; - node.raw = this.input.slice(this.start, this.end); - this.next(); - return this.finishNode(node, "Literal") -}; - -pp$3.parseParenExpression = function() { - this.expect(types.parenL); - var val = this.parseExpression(); - this.expect(types.parenR); - return val -}; - -pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; - if (this.options.ecmaVersion >= 6) { - this.next(); - - var innerStartPos = this.start, innerStartLoc = this.startLoc; - var exprList = [], first = true, lastIsComma = false; - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; - this.yieldPos = 0; - this.awaitPos = 0; - while (this.type !== types.parenR) { - first ? first = false : this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { - lastIsComma = true; - break - } else if (this$1.type === types.ellipsis) { - spreadStart = this$1.start; - exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - break - } else { - exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); - } - } - var innerEndPos = this.start, innerEndLoc = this.startLoc; - this.expect(types.parenR); - - if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { - this.checkPatternErrors(refDestructuringErrors, false); - this.checkYieldAwaitInDefaultParams(); - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.parseParenArrowList(startPos, startLoc, exprList) - } - - if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } - if (spreadStart) { this.unexpected(spreadStart); } - this.checkExpressionErrors(refDestructuringErrors, true); - this.yieldPos = oldYieldPos || this.yieldPos; - this.awaitPos = oldAwaitPos || this.awaitPos; - - if (exprList.length > 1) { - val = this.startNodeAt(innerStartPos, innerStartLoc); - val.expressions = exprList; - this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); - } else { - val = exprList[0]; - } - } else { - val = this.parseParenExpression(); - } - - if (this.options.preserveParens) { - var par = this.startNodeAt(startPos, startLoc); - par.expression = val; - return this.finishNode(par, "ParenthesizedExpression") - } else { - return val - } -}; - -pp$3.parseParenItem = function(item) { - return item -}; - -pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) -}; - -// New's precedence is slightly tricky. It must allow its argument to -// be a `[]` or dot subscript expression, but not a call — at least, -// not without wrapping it in parentheses. Thus, it uses the noCalls -// argument to parseSubscripts to prevent it from consuming the -// argument list. - -var empty$1 = []; - -pp$3.parseNew = function() { - var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { - node.meta = meta; - var containsEsc = this.containsEsc; - node.property = this.parseIdent(true); - if (node.property.name !== "target" || containsEsc) - { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } - if (!this.inFunction) - { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } - return this.finishNode(node, "MetaProperty") - } - var startPos = this.start, startLoc = this.startLoc; - node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); - if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } - else { node.arguments = empty$1; } - return this.finishNode(node, "NewExpression") -}; - -// Parse template expression. - -pp$3.parseTemplateElement = function(ref) { - var isTagged = ref.isTagged; - - var elem = this.startNode(); - if (this.type === types.invalidTemplate) { - if (!isTagged) { - this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); - } - elem.value = { - raw: this.value, - cooked: null - }; - } else { - elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), - cooked: this.value - }; - } - this.next(); - elem.tail = this.type === types.backQuote; - return this.finishNode(elem, "TemplateElement") -}; - -pp$3.parseTemplate = function(ref) { - var this$1 = this; - if ( ref === void 0 ) ref = {}; - var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; - - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement({isTagged: isTagged}); - node.quasis = [curElt]; - while (!curElt.tail) { - this$1.expect(types.dollarBraceL); - node.expressions.push(this$1.parseExpression()); - this$1.expect(types.braceR); - node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); - } - this.next(); - return this.finishNode(node, "TemplateLiteral") -}; - -pp$3.isAsyncProp = function(prop) { - return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && - (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && - !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -// Parse an object literal or binding pattern. - -pp$3.parseObj = function(isPattern, refDestructuringErrors) { - var this$1 = this; - - var node = this.startNode(), first = true, propHash = {}; - node.properties = []; - this.next(); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var prop = this$1.parseProperty(isPattern, refDestructuringErrors); - if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); } - node.properties.push(prop); - } - return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") -}; - -pp$3.parseProperty = function(isPattern, refDestructuringErrors) { - var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; - if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { - if (isPattern) { - prop.argument = this.parseIdent(false); - if (this.type === types.comma) { - this.raise(this.start, "Comma is not permitted after the rest element"); - } - return this.finishNode(prop, "RestElement") - } - // To disallow parenthesized identifier via `this.toAssignable()`. - if (this.type === types.parenL && refDestructuringErrors) { - if (refDestructuringErrors.parenthesizedAssign < 0) { - refDestructuringErrors.parenthesizedAssign = this.start; - } - if (refDestructuringErrors.parenthesizedBind < 0) { - refDestructuringErrors.parenthesizedBind = this.start; - } - } - // Parse argument. - prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); - // To disallow trailing comma via `this.toAssignable()`. - if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { - refDestructuringErrors.trailingComma = this.start; - } - // Finish - return this.finishNode(prop, "SpreadElement") - } - if (this.options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - if (isPattern || refDestructuringErrors) { - startPos = this.start; - startLoc = this.startLoc; - } - if (!isPattern) - { isGenerator = this.eat(types.star); } - } - var containsEsc = this.containsEsc; - this.parsePropertyName(prop); - if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { - isAsync = true; - isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); - this.parsePropertyName(prop, refDestructuringErrors); - } else { - isAsync = false; - } - this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); - return this.finishNode(prop, "Property") -}; - -pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { - if ((isGenerator || isAsync) && this.type === types.colon) - { this.unexpected(); } - - if (this.eat(types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); - prop.kind = "init"; - } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { - if (isPattern) { this.unexpected(); } - prop.kind = "init"; - prop.method = true; - prop.value = this.parseMethod(isGenerator, isAsync); - } else if (!isPattern && !containsEsc && - this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set") && - (this.type != types.comma && this.type != types.braceR)) { - if (isGenerator || isAsync) { this.unexpected(); } - prop.kind = prop.key.name; - this.parsePropertyName(prop); - prop.value = this.parseMethod(false); - var paramCount = prop.kind === "get" ? 0 : 1; - if (prop.value.params.length !== paramCount) { - var start = prop.value.start; - if (prop.kind === "get") - { this.raiseRecoverable(start, "getter should have no params"); } - else - { this.raiseRecoverable(start, "setter should have exactly one param"); } - } else { - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") - { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } - } - } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - this.checkUnreserved(prop.key); - prop.kind = "init"; - if (isPattern) { - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === types.eq && refDestructuringErrors) { - if (refDestructuringErrors.shorthandAssign < 0) - { refDestructuringErrors.shorthandAssign = this.start; } - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else { - prop.value = prop.key; - } - prop.shorthand = true; - } else { this.unexpected(); } -}; - -pp$3.parsePropertyName = function(prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(types.bracketL)) { - prop.computed = true; - prop.key = this.parseMaybeAssign(); - this.expect(types.bracketR); - return prop.key - } else { - prop.computed = false; - } - } - return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) -}; - -// Initialize empty function node. - -pp$3.initFunction = function(node) { - node.id = null; - if (this.options.ecmaVersion >= 6) { - node.generator = false; - node.expression = false; - } - if (this.options.ecmaVersion >= 8) - { node.async = false; } -}; - -// Parse object or class method. - -pp$3.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - - this.initFunction(node); - if (this.options.ecmaVersion >= 6) - { node.generator = isGenerator; } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - this.inGenerator = node.generator; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - this.enterFunctionScope(); - - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); - this.parseFunctionBody(node, false); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, "FunctionExpression") -}; - -// Parse arrow function expression with given parameters. - -pp$3.parseArrowExpression = function(node, params, isAsync) { - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, - oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; - - this.enterFunctionScope(); - this.initFunction(node); - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - this.inGenerator = false; - this.inAsync = node.async; - this.yieldPos = 0; - this.awaitPos = 0; - this.inFunction = true; - - node.params = this.toAssignableList(params, true); - this.parseFunctionBody(node, true); - - this.inGenerator = oldInGen; - this.inAsync = oldInAsync; - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - this.inFunction = oldInFunc; - return this.finishNode(node, "ArrowFunctionExpression") -}; - -// Parse function body and check parameters. - -pp$3.parseFunctionBody = function(node, isArrowFunction) { - var isExpression = isArrowFunction && this.type !== types.braceL; - var oldStrict = this.strict, useStrict = false; - - if (isExpression) { - node.body = this.parseMaybeAssign(); - node.expression = true; - this.checkParams(node, false); - } else { - var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); - if (!oldStrict || nonSimple) { - useStrict = this.strictDirective(this.end); - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - if (useStrict && nonSimple) - { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } - } - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldLabels = this.labels; - this.labels = []; - if (useStrict) { this.strict = true; } - - // Add the params to varDeclaredNames to ensure that an error is thrown - // if a let/const declaration in the function clashes with one of the params. - this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); - node.body = this.parseBlock(false); - node.expression = false; - this.adaptDirectivePrologue(node.body.body); - this.labels = oldLabels; - } - this.exitFunctionScope(); - - if (this.strict && node.id) { - // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' - this.checkLVal(node.id, "none"); - } - this.strict = oldStrict; -}; - -pp$3.isSimpleParamList = function(params) { - for (var i = 0, list = params; i < list.length; i += 1) - { - var param = list[i]; - - if (param.type !== "Identifier") { return false - } } - return true -}; - -// Checks function params for various disallowed patterns such as using "eval" -// or "arguments" and duplicate parameters. - -pp$3.checkParams = function(node, allowDuplicates) { - var this$1 = this; - - var nameHash = {}; - for (var i = 0, list = node.params; i < list.length; i += 1) - { - var param = list[i]; - - this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); - } -}; - -// Parses a comma-separated list of expressions, and returns them as -// an array. `close` is the token type that ends the list, and -// `allowEmpty` can be turned on to allow subsequent commas with -// nothing in between them to be parsed as `null` (which is needed -// for array literals). - -pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (!first) { - this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } - } else { first = false; } - - var elt = (void 0); - if (allowEmpty && this$1.type === types.comma) - { elt = null; } - else if (this$1.type === types.ellipsis) { - elt = this$1.parseSpread(refDestructuringErrors); - if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) - { refDestructuringErrors.trailingComma = this$1.start; } - } else { - elt = this$1.parseMaybeAssign(false, refDestructuringErrors); - } - elts.push(elt); - } - return elts -}; - -pp$3.checkUnreserved = function(ref) { - var start = ref.start; - var end = ref.end; - var name = ref.name; - - if (this.inGenerator && name === "yield") - { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } - if (this.inAsync && name === "await") - { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } - if (this.isKeyword(name)) - { this.raise(start, ("Unexpected keyword '" + name + "'")); } - if (this.options.ecmaVersion < 6 && - this.input.slice(start, end).indexOf("\\") != -1) { return } - var re = this.strict ? this.reservedWordsStrict : this.reservedWords; - if (re.test(name)) { - if (!this.inAsync && name === "await") - { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); } - this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); - } -}; - -// Parse the next token as an identifier. If `liberal` is true (used -// when parsing properties), it will also convert keywords into -// identifiers. - -pp$3.parseIdent = function(liberal, isBinding) { - var node = this.startNode(); - if (liberal && this.options.allowReserved == "never") { liberal = false; } - if (this.type === types.name) { - node.name = this.value; - } else if (this.type.keyword) { - node.name = this.type.keyword; - - // To fix https://github.com/acornjs/acorn/issues/575 - // `class` and `function` keywords push new context into this.context. - // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. - // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword - if ((node.name === "class" || node.name === "function") && - (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { - this.context.pop(); - } - } else { - this.unexpected(); - } - this.next(); - this.finishNode(node, "Identifier"); - if (!liberal) { this.checkUnreserved(node); } - return node -}; - -// Parses yield expression inside generator. - -pp$3.parseYield = function() { - if (!this.yieldPos) { this.yieldPos = this.start; } - - var node = this.startNode(); - this.next(); - if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(types.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression") -}; - -pp$3.parseAwait = function() { - if (!this.awaitPos) { this.awaitPos = this.start; } - - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeUnary(null, true); - return this.finishNode(node, "AwaitExpression") -}; - -var pp$4 = Parser.prototype; - -// This function is used to raise exceptions on parse errors. It -// takes an offset integer (into the current `input`) to indicate -// the location of the error, attaches the position to the end -// of the error message, and then raises a `SyntaxError` with that -// message. - -pp$4.raise = function(pos, message) { - var loc = getLineInfo(this.input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos; err.loc = loc; err.raisedAt = this.pos; - throw err -}; - -pp$4.raiseRecoverable = pp$4.raise; - -pp$4.curPosition = function() { - if (this.options.locations) { - return new Position(this.curLine, this.pos - this.lineStart) - } -}; - -var pp$5 = Parser.prototype; - -// Object.assign polyfill -var assign = Object.assign || function(target) { - var sources = [], len = arguments.length - 1; - while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; - - for (var i = 0, list = sources; i < list.length; i += 1) { - var source = list[i]; - - for (var key in source) { - if (has(source, key)) { - target[key] = source[key]; - } - } - } - return target -}; - -// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. - -pp$5.enterFunctionScope = function() { - // var: a hash of var-declared names in the current lexical scope - // lexical: a hash of lexically-declared names in the current lexical scope - // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) - // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) - this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); -}; - -pp$5.exitFunctionScope = function() { - this.scopeStack.pop(); -}; - -pp$5.enterLexicalScope = function() { - var parentScope = this.scopeStack[this.scopeStack.length - 1]; - var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; - - this.scopeStack.push(childScope); - assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); -}; - -pp$5.exitLexicalScope = function() { - var childScope = this.scopeStack.pop(); - var parentScope = this.scopeStack[this.scopeStack.length - 1]; - - assign(parentScope.childVar, childScope.var, childScope.childVar); -}; - -/** - * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` - * in the current lexical scope or any of the parent lexical scopes in this function. - */ -pp$5.canDeclareVarName = function(name) { - var currentScope = this.scopeStack[this.scopeStack.length - 1]; - - return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) -}; - -/** - * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` - * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in - * any child lexical scopes in this function. - */ -pp$5.canDeclareLexicalName = function(name) { - var currentScope = this.scopeStack[this.scopeStack.length - 1]; - - return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) -}; - -pp$5.declareVarName = function(name) { - this.scopeStack[this.scopeStack.length - 1].var[name] = true; -}; - -pp$5.declareLexicalName = function(name) { - this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; -}; - -var Node = function Node(parser, pos, loc) { - this.type = ""; - this.start = pos; - this.end = 0; - if (parser.options.locations) - { this.loc = new SourceLocation(parser, loc); } - if (parser.options.directSourceFile) - { this.sourceFile = parser.options.directSourceFile; } - if (parser.options.ranges) - { this.range = [pos, 0]; } -}; - -// Start an AST node, attaching a start offset. - -var pp$6 = Parser.prototype; - -pp$6.startNode = function() { - return new Node(this, this.start, this.startLoc) -}; - -pp$6.startNodeAt = function(pos, loc) { - return new Node(this, pos, loc) -}; - -// Finish an AST node, adding `type` and `end` properties. - -function finishNodeAt(node, type, pos, loc) { - node.type = type; - node.end = pos; - if (this.options.locations) - { node.loc.end = loc; } - if (this.options.ranges) - { node.range[1] = pos; } - return node -} - -pp$6.finishNode = function(node, type) { - return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) -}; - -// Finish node at given position - -pp$6.finishNodeAt = function(node, type, pos, loc) { - return finishNodeAt.call(this, node, type, pos, loc) -}; - -// The algorithm used to determine whether a regexp can appear at a -// given point in the program is loosely based on sweet.js' approach. -// See https://github.com/mozilla/sweet.js/wiki/design - -var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { - this.token = token; - this.isExpr = !!isExpr; - this.preserveSpace = !!preserveSpace; - this.override = override; - this.generator = !!generator; -}; - -var types$1 = { - b_stat: new TokContext("{", false), - b_expr: new TokContext("{", true), - b_tmpl: new TokContext("${", false), - p_stat: new TokContext("(", false), - p_expr: new TokContext("(", true), - q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), - f_stat: new TokContext("function", false), - f_expr: new TokContext("function", true), - f_expr_gen: new TokContext("function", true, false, null, true), - f_gen: new TokContext("function", false, false, null, true) -}; - -var pp$7 = Parser.prototype; - -pp$7.initialContext = function() { - return [types$1.b_stat] -}; - -pp$7.braceIsBlock = function(prevType) { - var parent = this.curContext(); - if (parent === types$1.f_expr || parent === types$1.f_stat) - { return true } - if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) - { return !parent.isExpr } - - // The check for `tt.name && exprAllowed` detects whether we are - // after a `yield` or `of` construct. See the `updateContext` for - // `tt.name`. - if (prevType === types._return || prevType == types.name && this.exprAllowed) - { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } - if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow) - { return true } - if (prevType == types.braceL) - { return parent === types$1.b_stat } - if (prevType == types._var || prevType == types.name) - { return false } - return !this.exprAllowed -}; - -pp$7.inGeneratorContext = function() { - var this$1 = this; - - for (var i = this.context.length - 1; i >= 1; i--) { - var context = this$1.context[i]; - if (context.token === "function") - { return context.generator } - } - return false -}; - -pp$7.updateContext = function(prevType) { - var update, type = this.type; - if (type.keyword && prevType == types.dot) - { this.exprAllowed = false; } - else if (update = type.updateContext) - { update.call(this, prevType); } - else - { this.exprAllowed = type.beforeExpr; } -}; - -// Token-specific context update code - -types.parenR.updateContext = types.braceR.updateContext = function() { - if (this.context.length == 1) { - this.exprAllowed = true; - return - } - var out = this.context.pop(); - if (out === types$1.b_stat && this.curContext().token === "function") { - out = this.context.pop(); - } - this.exprAllowed = !out.isExpr; -}; - -types.braceL.updateContext = function(prevType) { - this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); - this.exprAllowed = true; -}; - -types.dollarBraceL.updateContext = function() { - this.context.push(types$1.b_tmpl); - this.exprAllowed = true; -}; - -types.parenL.updateContext = function(prevType) { - var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; - this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); - this.exprAllowed = true; -}; - -types.incDec.updateContext = function() { - // tokExprAllowed stays unchanged -}; - -types._function.updateContext = types._class.updateContext = function(prevType) { - if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && - !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) - { this.context.push(types$1.f_expr); } - else - { this.context.push(types$1.f_stat); } - this.exprAllowed = false; -}; - -types.backQuote.updateContext = function() { - if (this.curContext() === types$1.q_tmpl) - { this.context.pop(); } - else - { this.context.push(types$1.q_tmpl); } - this.exprAllowed = false; -}; - -types.star.updateContext = function(prevType) { - if (prevType == types._function) { - var index = this.context.length - 1; - if (this.context[index] === types$1.f_expr) - { this.context[index] = types$1.f_expr_gen; } - else - { this.context[index] = types$1.f_gen; } - } - this.exprAllowed = true; -}; - -types.name.updateContext = function(prevType) { - var allowed = false; - if (this.options.ecmaVersion >= 6) { - if (this.value == "of" && !this.exprAllowed || - this.value == "yield" && this.inGeneratorContext()) - { allowed = true; } - } - this.exprAllowed = allowed; -}; - -// Object type used to represent tokens. Note that normally, tokens -// simply exist as properties on the parser object. This is only -// used for the onToken callback and the external tokenizer. - -var Token = function Token(p) { - this.type = p.type; - this.value = p.value; - this.start = p.start; - this.end = p.end; - if (p.options.locations) - { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } - if (p.options.ranges) - { this.range = [p.start, p.end]; } -}; - -// ## Tokenizer - -var pp$8 = Parser.prototype; - -// Are we running under Rhino? -var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; - -// Move to the next token - -pp$8.next = function() { - if (this.options.onToken) - { this.options.onToken(new Token(this)); } - - this.lastTokEnd = this.end; - this.lastTokStart = this.start; - this.lastTokEndLoc = this.endLoc; - this.lastTokStartLoc = this.startLoc; - this.nextToken(); -}; - -pp$8.getToken = function() { - this.next(); - return new Token(this) -}; - -// If we're in an ES6 environment, make parsers iterable -if (typeof Symbol !== "undefined") - { pp$8[Symbol.iterator] = function() { + pp$1.checkVariableExport = function (exports, decls) { var this$1 = this; - return { - next: function () { - var token = this$1.getToken(); - return { - done: token.type === types.eof, - value: token + if (!exports) { + return; + } + for (var i = 0, list = decls; i < list.length; i += 1) { + var decl = list[i]; + + this$1.checkPatternExport(exports, decl.id); + } + }; + + pp$1.shouldParseExportStatement = function () { + return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction(); + }; + + // Parses a comma-separated list of module exports. + + pp$1.parseExportSpecifiers = function (exports) { + var this$1 = this; + + var nodes = [], + first = true; + // export { x, y as z } [from '...'] + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { + break; } - } - } - }; } - -// Toggle strict mode. Re-reads the next number or string to please -// pedantic tests (`"use strict"; 010;` should fail). - -pp$8.curContext = function() { - return this.context[this.context.length - 1] -}; - -// Read a single token, updating the parser object's token-related -// properties. - -pp$8.nextToken = function() { - var curContext = this.curContext(); - if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } - - this.start = this.pos; - if (this.options.locations) { this.startLoc = this.curPosition(); } - if (this.pos >= this.input.length) { return this.finishToken(types.eof) } - - if (curContext.override) { return curContext.override(this) } - else { this.readToken(this.fullCharCodeAtPos()); } -}; - -pp$8.readToken = function(code) { - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) - { return this.readWord() } - - return this.getTokenFromCode(code) -}; - -pp$8.fullCharCodeAtPos = function() { - var code = this.input.charCodeAt(this.pos); - if (code <= 0xd7ff || code >= 0xe000) { return code } - var next = this.input.charCodeAt(this.pos + 1); - return (code << 10) + next - 0x35fdc00 -}; - -pp$8.skipBlockComment = function() { - var this$1 = this; - - var startLoc = this.options.onComment && this.curPosition(); - var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); - if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } - this.pos = end + 2; - if (this.options.locations) { - lineBreakG.lastIndex = start; - var match; - while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { - ++this$1.curLine; - this$1.lineStart = match.index + match[0].length; - } - } - if (this.options.onComment) - { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, - startLoc, this.curPosition()); } -}; - -pp$8.skipLineComment = function(startSkip) { - var this$1 = this; - - var start = this.pos; - var startLoc = this.options.onComment && this.curPosition(); - var ch = this.input.charCodeAt(this.pos += startSkip); - while (this.pos < this.input.length && !isNewLine(ch)) { - ch = this$1.input.charCodeAt(++this$1.pos); - } - if (this.options.onComment) - { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, - startLoc, this.curPosition()); } -}; - -// Called at the start of the parse and after every token. Skips -// whitespace and comments, and. - -pp$8.skipSpace = function() { - var this$1 = this; - - loop: while (this.pos < this.input.length) { - var ch = this$1.input.charCodeAt(this$1.pos); - switch (ch) { - case 32: case 160: // ' ' - ++this$1.pos; - break - case 13: - if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { - ++this$1.pos; - } - case 10: case 8232: case 8233: - ++this$1.pos; - if (this$1.options.locations) { - ++this$1.curLine; - this$1.lineStart = this$1.pos; - } - break - case 47: // '/' - switch (this$1.input.charCodeAt(this$1.pos + 1)) { - case 42: // '*' - this$1.skipBlockComment(); - break - case 47: - this$1.skipLineComment(2); - break - default: - break loop - } - break - default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this$1.pos; } else { - break loop + first = false; + } + + var node = this$1.startNode(); + node.local = this$1.parseIdent(true); + node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; + this$1.checkExport(exports, node.exported.name, node.exported.start); + nodes.push(this$1.finishNode(node, "ExportSpecifier")); + } + return nodes; + }; + + // Parses import declaration. + + pp$1.parseImport = function (node) { + this.next(); + // import '...' + if (this.type === types.string) { + node.specifiers = empty; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration"); + }; + + // Parses a comma-separated list of module imports. + + pp$1.parseImportSpecifiers = function () { + var this$1 = this; + + var nodes = [], + first = true; + if (this.type === types.name) { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLVal(node.local, BIND_LEXICAL); + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); + if (!this.eat(types.comma)) { + return nodes; } } - } -}; - -// Called at the end of every token. Sets `end`, `val`, and -// maintains `context` and `exprAllowed`, and skips the space after -// the token, so that the next one's `start` will point at the -// right position. - -pp$8.finishToken = function(type, val) { - this.end = this.pos; - if (this.options.locations) { this.endLoc = this.curPosition(); } - var prevType = this.type; - this.type = type; - this.value = val; - - this.updateContext(prevType); -}; - -// ### Token reading - -// This is the function that is called to fetch the next token. It -// is somewhat obscure, because it works in character codes rather -// than characters, and because operator parsing has been inlined -// into it. -// -// All in the name of speed. -// -pp$8.readToken_dot = function() { - var next = this.input.charCodeAt(this.pos + 1); - if (next >= 48 && next <= 57) { return this.readNumber(true) } - var next2 = this.input.charCodeAt(this.pos + 2); - if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' - this.pos += 3; - return this.finishToken(types.ellipsis) - } else { - ++this.pos; - return this.finishToken(types.dot) - } -}; - -pp$8.readToken_slash = function() { // '/' - var next = this.input.charCodeAt(this.pos + 1); - if (this.exprAllowed) { ++this.pos; return this.readRegexp() } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.slash, 1) -}; - -pp$8.readToken_mult_modulo_exp = function(code) { // '%*' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - var tokentype = code === 42 ? types.star : types.modulo; - - // exponentiation operator ** and **= - if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { - ++size; - tokentype = types.starstar; - next = this.input.charCodeAt(this.pos + 2); - } - - if (next === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(tokentype, size) -}; - -pp$8.readToken_pipe_amp = function(code) { // '|&' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) -}; - -pp$8.readToken_caret = function() { // '^' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.bitwiseXOR, 1) -}; - -pp$8.readToken_plus_min = function(code) { // '+-' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { - if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && - (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { - // A `-->` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken() + if (this.type === types.star) { + var node$1 = this.startNode(); + this.next(); + this.expectContextual("as"); + node$1.local = this.parseIdent(); + this.checkLVal(node$1.local, BIND_LEXICAL); + nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); + return nodes; } - return this.finishOp(types.incDec, 2) - } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.plusMin, 1) -}; + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this$1.expect(types.comma); + if (this$1.afterTrailingComma(types.braceR)) { + break; + } + } else { + first = false; + } -pp$8.readToken_lt_gt = function(code) { // '<>' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(types.bitShift, size) - } - if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { - // `` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken(); + } + return this.finishOp(types.incDec, 2); + } + if (next === 61) { + return this.finishOp(types.assign, 2); + } + return this.finishOp(types.plusMin, 1); + }; + + pp$8.readToken_lt_gt = function (code) { + // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { + return this.finishOp(types.assign, size + 1); + } + return this.finishOp(types.bitShift, size); + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && this.input.charCodeAt(this.pos + 3) === 45) { + // ` {"no-alert": "2 no-console: 2"} - // Should ignore that case as well. - if (ConfigOps.isEverySeverityValid(items)) { - return { - success: true, - config: items - }; - } - } catch (ex) {} - - // ignore to parse the string by a fallback. - - - /* - * Optionator cannot parse commaless notations. - * But we are supporting that. So this is a fallback for that. - */ - items = {}; - string = string.replace(/([a-zA-Z0-9\-/]+):/g, "\"$1\":").replace(/(]|[0-9])\s+(?=")/, "$1,"); - try { - items = JSON.parse("{" + string + "}"); - } catch (ex) { - return { - success: false, - error: { - ruleId: null, - fatal: true, - severity: 2, - source: null, - message: "Failed to parse JSON from '" + string + "': " + ex.message, - line: location.start.line, - column: location.start.column + 1 - } - }; - } - - return { - success: true, - config: items - }; -} - -/** - * Parses a config of values separated by comma. - * @param {string} string The string to parse. - * @returns {Object} Result map of values and true values - */ -function parseListConfig(string) { - var items = {}; - - // Collapse whitespace around , - string = string.replace(/\s*,\s*/g, ","); - - string.split(/,+/).forEach(function (name) { - name = name.trim(); - if (!name) { - return; - } - items[name] = true; - }); - return items; -} - /** * Ensures that variables representing built-in properties of the Global Object, * and any globals declared by special block comments, are present in the global * scope. * @param {Scope} globalScope The global scope. - * @param {Object} config The existing configuration data. - * @param {Environments} envContext Env context + * @param {Object} configGlobals The globals declared in configuration + * @param {{exportedVariables: Object, enabledGlobals: Object}} commentDirectives Directives from comment configuration * @returns {void} */ -function addDeclaredGlobals(globalScope, config, envContext) { - var declaredGlobals = {}, - exportedGlobals = {}, - explicitGlobals = {}, - builtin = envContext.get("builtin"); - - Object.assign(declaredGlobals, builtin); - - Object.keys(config.env).filter(function (name) { - return config.env[name]; - }).forEach(function (name) { - var env = envContext.get(name), - environmentGlobals = env && env.globals; - - if (environmentGlobals) { - Object.assign(declaredGlobals, environmentGlobals); - } - }); - - Object.assign(exportedGlobals, config.exported); - Object.assign(declaredGlobals, config.globals); - Object.assign(explicitGlobals, config.astGlobals); - - Object.keys(declaredGlobals).forEach(function (name) { +function addDeclaredGlobals(globalScope, configGlobals, commentDirectives) { + Object.keys(configGlobals).forEach(function (name) { var variable = globalScope.set.get(name); if (!variable) { @@ -55189,24 +62049,24 @@ function addDeclaredGlobals(globalScope, config, envContext) { globalScope.variables.push(variable); globalScope.set.set(name, variable); } - variable.writeable = declaredGlobals[name]; + variable.writeable = configGlobals[name]; }); - Object.keys(explicitGlobals).forEach(function (name) { + Object.keys(commentDirectives.enabledGlobals).forEach(function (name) { var variable = globalScope.set.get(name); if (!variable) { variable = new eslintScope.Variable(name, globalScope); variable.eslintExplicitGlobal = true; - variable.eslintExplicitGlobalComment = explicitGlobals[name].comment; + variable.eslintExplicitGlobalComment = commentDirectives.enabledGlobals[name].comment; globalScope.variables.push(variable); globalScope.set.set(name, variable); } - variable.writeable = explicitGlobals[name].value; + variable.writeable = commentDirectives.enabledGlobals[name].value; }); // mark all exported variables as such - Object.keys(exportedGlobals).forEach(function (name) { + Object.keys(commentDirectives.exportedVariables).forEach(function (name) { var variable = globalScope.set.get(name); if (variable) { @@ -55248,7 +62108,7 @@ function addDeclaredGlobals(globalScope, config, envContext) { * @returns {DisableDirective[]} Directives from the comment */ function createDisableDirectives(type, loc, value) { - var ruleIds = Object.keys(parseListConfig(value)); + var ruleIds = Object.keys(commentParser.parseListConfig(value)); var directiveRules = ruleIds.length ? ruleIds : [null]; return directiveRules.map(function (ruleId) { @@ -55262,112 +62122,105 @@ function createDisableDirectives(type, loc, value) { * where reporting is disabled or enabled and merges them with reporting config. * @param {string} filename The file being checked. * @param {ASTNode} ast The top node of the AST. - * @param {Object} config The existing configuration data. * @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules - * @returns {{config: Object, problems: Problem[], disableDirectives: DisableDirective[]}} - * Modified config object, along with any problems encountered while parsing config comments + * @returns {{configuredRules: Object, enabledGlobals: Object, exportedVariables: Object, problems: Problem[], disableDirectives: DisableDirective[]}} + * A collection of the directive comments that were found, along with any problems that occurred when parsing */ -function modifyConfigsFromComments(filename, ast, config, ruleMapper) { - - var commentConfig = { - exported: {}, - astGlobals: {}, - rules: {}, - env: {} - }; - var commentRules = {}; +function getDirectiveComments(filename, ast, ruleMapper) { + var configuredRules = {}; + var enabledGlobals = {}; + var exportedVariables = {}; var problems = []; var disableDirectives = []; ast.comments.filter(function (token) { return token.type !== "Shebang"; }).forEach(function (comment) { + var trimmedCommentText = comment.value.trim(); + var match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(trimmedCommentText); - var value = comment.value.trim(); - var match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value); + if (!match) { + return; + } - if (match) { - value = value.slice(match.index + match[1].length); - if (comment.type === "Block") { - switch (match[1]) { - case "exported": - Object.assign(commentConfig.exported, parseBooleanConfig(value, comment)); - break; + var directiveValue = trimmedCommentText.slice(match.index + match[1].length); - case "globals": - case "global": - Object.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment)); - break; + if (/^eslint-disable-(next-)?line$/.test(match[1])) { + if (comment.loc.start.line === comment.loc.end.line) { + var directiveType = match[1].slice("eslint-".length); - case "eslint-disable": - [].push.apply(disableDirectives, createDisableDirectives("disable", comment.loc.start, value)); - break; - - case "eslint-disable-line": - if (comment.loc.start.line === comment.loc.end.line) { - [].push.apply(disableDirectives, createDisableDirectives("disable-line", comment.loc.start, value)); - } - break; - - case "eslint-disable-next-line": - if (comment.loc.start.line === comment.loc.end.line) { - [].push.apply(disableDirectives, createDisableDirectives("disable-next-line", comment.loc.start, value)); - } - break; - - case "eslint-enable": - [].push.apply(disableDirectives, createDisableDirectives("enable", comment.loc.start, value)); - break; - - case "eslint": - { - var parseResult = parseJsonConfig(value, comment.loc); - - if (parseResult.success) { - Object.keys(parseResult.config).forEach(function (name) { - var ruleValue = parseResult.config[name]; - - try { - validator.validateRuleOptions(ruleMapper(name), name, ruleValue); - } catch (err) { - problems.push({ - ruleId: name, - severity: 2, - source: null, - message: err.message, - line: comment.loc.start.line, - column: comment.loc.start.column + 1, - endLine: comment.loc.end.line, - endColumn: comment.loc.end.column + 1, - nodeType: null - }); - } - commentRules[name] = ruleValue; - }); - } else { - problems.push(parseResult.error); - } - - break; - } - - // no default - } + disableDirectives.push.apply(disableDirectives, _toConsumableArray(createDisableDirectives(directiveType, comment.loc.start, directiveValue))); } else { - // comment.type === "Line" - if (match[1] === "eslint-disable-line") { - [].push.apply(disableDirectives, createDisableDirectives("disable-line", comment.loc.start, value)); - } else if (match[1] === "eslint-disable-next-line") { - [].push.apply(disableDirectives, createDisableDirectives("disable-next-line", comment.loc.start, value)); - } + problems.push({ + ruleId: null, + severity: 2, + message: match[1] + " comment should not span multiple lines.", + line: comment.loc.start.line, + column: comment.loc.start.column + 1, + endLine: comment.loc.end.line, + endColumn: comment.loc.end.column + 1, + nodeType: null + }); + } + } else if (comment.type === "Block") { + switch (match[1]) { + case "exported": + Object.assign(exportedVariables, commentParser.parseBooleanConfig(directiveValue, comment)); + break; + + case "globals": + case "global": + Object.assign(enabledGlobals, commentParser.parseBooleanConfig(directiveValue, comment)); + break; + + case "eslint-disable": + disableDirectives.push.apply(disableDirectives, _toConsumableArray(createDisableDirectives("disable", comment.loc.start, directiveValue))); + break; + + case "eslint-enable": + disableDirectives.push.apply(disableDirectives, _toConsumableArray(createDisableDirectives("enable", comment.loc.start, directiveValue))); + break; + + case "eslint": + { + var parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc); + + if (parseResult.success) { + Object.keys(parseResult.config).forEach(function (name) { + var ruleValue = parseResult.config[name]; + + try { + validator.validateRuleOptions(ruleMapper(name), name, ruleValue); + } catch (err) { + problems.push({ + ruleId: name, + severity: 2, + message: err.message, + line: comment.loc.start.line, + column: comment.loc.start.column + 1, + endLine: comment.loc.end.line, + endColumn: comment.loc.end.column + 1, + nodeType: null + }); + } + configuredRules[name] = ruleValue; + }); + } else { + problems.push(parseResult.error); + } + + break; + } + + // no default } } }); - Object.assign(commentConfig.rules, commentRules); - return { - config: ConfigOps.merge(config, commentConfig), + configuredRules: configuredRules, + enabledGlobals: enabledGlobals, + exportedVariables: exportedVariables, problems: problems, disableDirectives: disableDirectives }; @@ -55383,7 +62236,7 @@ function normalizeEcmaVersion(ecmaVersion, isModule) { // Need at least ES6 for modules if (isModule && (!ecmaVersion || ecmaVersion < 6)) { - ecmaVersion = 6; + return 6; } /* @@ -55391,70 +62244,12 @@ function normalizeEcmaVersion(ecmaVersion, isModule) { * ES2015, which corresponds with ES6 (or a difference of 2009). */ if (ecmaVersion >= 2015) { - ecmaVersion -= 2009; + return ecmaVersion - 2009; } return ecmaVersion; } -/** - * Process initial config to make it safe to extend by file comment config - * @param {Object} config Initial config - * @param {Environments} envContext Env context - * @returns {Object} Processed config - */ -function prepareConfig(config, envContext) { - config.globals = config.globals || {}; - var copiedRules = {}; - var parserOptions = {}; - - if (_typeof(config.rules) === "object") { - Object.keys(config.rules).forEach(function (k) { - var rule = config.rules[k]; - - if (rule === null) { - throw new Error("Invalid config for rule '" + k + "'."); - } - if (Array.isArray(rule)) { - copiedRules[k] = rule.slice(); - } else { - copiedRules[k] = rule; - } - }); - } - - // merge in environment parserOptions - if (_typeof(config.env) === "object") { - Object.keys(config.env).forEach(function (envName) { - var env = envContext.get(envName); - - if (config.env[envName] && env && env.parserOptions) { - parserOptions = ConfigOps.merge(parserOptions, env.parserOptions); - } - }); - } - - var preparedConfig = { - rules: copiedRules, - parser: config.parser || defaultConfig.parser, - globals: ConfigOps.merge(defaultConfig.globals, config.globals), - env: ConfigOps.merge(defaultConfig.env, config.env || {}), - settings: ConfigOps.merge(defaultConfig.settings, config.settings || {}), - parserOptions: ConfigOps.merge(parserOptions, config.parserOptions || {}) - }; - var isModule = preparedConfig.parserOptions.sourceType === "module"; - - if (isModule) { - - // can't have global return inside of modules - preparedConfig.parserOptions.ecmaFeatures = Object.assign({}, preparedConfig.parserOptions.ecmaFeatures, { globalReturn: false }); - } - - preparedConfig.parserOptions.ecmaVersion = normalizeEcmaVersion(preparedConfig.parserOptions.ecmaVersion, isModule); - - return preparedConfig; -} - var eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g; /** @@ -55469,12 +62264,77 @@ function findEslintEnv(text) { eslintEnvPattern.lastIndex = 0; while (match = eslintEnvPattern.exec(text)) { - retv = Object.assign(retv || {}, parseListConfig(match[1])); + retv = Object.assign(retv || {}, commentParser.parseListConfig(match[1])); } return retv; } +/** + * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a + * consistent shape. + * @param {(string|{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean})} providedOptions Options + * @returns {{reportUnusedDisableDirectives: boolean, filename: string, allowInlineConfig: boolean}} Normalized options + */ +function normalizeVerifyOptions(providedOptions) { + var isObjectOptions = (typeof providedOptions === "undefined" ? "undefined" : _typeof(providedOptions)) === "object"; + var providedFilename = isObjectOptions ? providedOptions.filename : providedOptions; + + return { + filename: typeof providedFilename === "string" ? providedFilename : "", + allowInlineConfig: !isObjectOptions || providedOptions.allowInlineConfig !== false, + reportUnusedDisableDirectives: isObjectOptions && !!providedOptions.reportUnusedDisableDirectives + }; +} + +/** + * Combines the provided parserOptions with the options from environments + * @param {string} parserName The parser name which uses this options. + * @param {Object} providedOptions The provided 'parserOptions' key in a config + * @param {Environment[]} enabledEnvironments The environments enabled in configuration and with inline comments + * @returns {Object} Resulting parser options after merge + */ +function resolveParserOptions(parserName, providedOptions, enabledEnvironments) { + var parserOptionsFromEnv = enabledEnvironments.filter(function (env) { + return env.parserOptions; + }).reduce(function (parserOptions, env) { + return ConfigOps.merge(parserOptions, env.parserOptions); + }, {}); + + var mergedParserOptions = ConfigOps.merge(parserOptionsFromEnv, providedOptions || {}); + + var isModule = mergedParserOptions.sourceType === "module"; + + if (isModule) { + + // can't have global return inside of modules + mergedParserOptions.ecmaFeatures = Object.assign({}, mergedParserOptions.ecmaFeatures, { globalReturn: false }); + } + + mergedParserOptions.ecmaVersion = normalizeEcmaVersion(mergedParserOptions.ecmaVersion, isModule); + + // TODO: For backward compatibility. Will remove on v6.0.0. + if (parserName === DEFAULT_PARSER_NAME && mergedParserOptions.ecmaFeatures && mergedParserOptions.ecmaFeatures.experimentalObjectRestSpread && (!mergedParserOptions.ecmaVersion || mergedParserOptions.ecmaVersion < 9)) { + mergedParserOptions.ecmaVersion = 9; + } + + return mergedParserOptions; +} + +/** + * Combines the provided globals object with the globals from environments + * @param {Object} providedGlobals The 'globals' key in a config + * @param {Environments[]} enabledEnvironments The environments enabled in configuration and with inline comments + * @returns {Object} The resolved globals object + */ +function resolveGlobals(providedGlobals, enabledEnvironments) { + return Object.assign.apply(Object, [{}].concat(_toConsumableArray(enabledEnvironments.filter(function (env) { + return env.globals; + }).map(function (env) { + return env.globals; + })), [providedGlobals])); +} + /** * Strips Unicode BOM from a given text. * @@ -55534,13 +62394,15 @@ function analyzeScope(ast, parserOptions, visitorKeys) { * as possible * @param {string} text The text to parse. * @param {Object} providedParserOptions Options to pass to the parser - * @param {Object} parser The parser module + * @param {string} parserName The name of the parser + * @param {Map} parserMap A map from names to loaded parsers * @param {string} filePath The path to the file being parsed. * @returns {{success: false, error: Problem}|{success: true, sourceCode: SourceCode}} * An object containing the AST and parser services if parsing was successful, or the error if parsing failed * @private */ -function parse(text, providedParserOptions, parser, filePath) { +function parse(text, providedParserOptions, parserName, parserMap, filePath) { + var textToParse = stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, function (match, captured) { return "//" + captured; }); @@ -55555,6 +62417,24 @@ function parse(text, providedParserOptions, parser, filePath) { filePath: filePath }); + var parser = void 0; + + try { + parser = parserMap.get(parserName) || require(parserName); + } catch (ex) { + return { + success: false, + error: { + ruleId: null, + fatal: true, + severity: 2, + message: ex.message, + line: 0, + column: 0 + } + }; + } + /* * Check for parsing errors first. If there's a parsing error, nothing * else can happen. However, a parsing error does not throw an error @@ -55589,7 +62469,6 @@ function parse(text, providedParserOptions, parser, filePath) { // If the message includes a leading line number, strip it: var message = "Parsing error: " + ex.message.replace(/^line \d+:/i, "").trim(); - var source = ex.lineNumber ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null; return { success: false, @@ -55597,7 +62476,6 @@ function parse(text, providedParserOptions, parser, filePath) { ruleId: null, fatal: true, severity: 2, - source: source, message: message, line: ex.lineNumber, column: ex.column @@ -55610,24 +62488,15 @@ function parse(text, providedParserOptions, parser, filePath) { * Gets the scope for the current node * @param {ScopeManager} scopeManager The scope manager for this AST * @param {ASTNode} currentNode The node to get the scope of - * @param {number} ecmaVersion The `ecmaVersion` setting that this code was parsed with * @returns {eslint-scope.Scope} The scope information for this node */ -function _getScope(scopeManager, currentNode, ecmaVersion) { - var initialNode = void 0; +function _getScope(scopeManager, currentNode) { - // if current node introduces a scope, add it to the list - if (["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(currentNode.type) >= 0 || ecmaVersion >= 6 && ["BlockStatement", "SwitchStatement", "CatchClause"].indexOf(currentNode.type) >= 0) { - initialNode = currentNode; - } else { - initialNode = currentNode.parent; - } + // On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope. + var inner = currentNode.type !== "Program"; - // Ascend the current node's parents - for (var node = initialNode; node; node = node.parent) { - - // Get the innermost scope - var scope = scopeManager.acquire(node, true); + for (var node = currentNode; node; node = node.parent) { + var scope = scopeManager.acquire(node, inner); if (scope) { if (scope.type === "function-expression-name") { @@ -55651,7 +62520,7 @@ function _getScope(scopeManager, currentNode, ecmaVersion) { function _markVariableAsUsed(scopeManager, currentNode, parserOptions, name) { var hasGlobalReturn = parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn; var specialScope = hasGlobalReturn || parserOptions.sourceType === "module"; - var currentScope = _getScope(scopeManager, currentNode, parserOptions.ecmaVersion); + var currentScope = _getScope(scopeManager, currentNode); // Special Node.js scope means we need to start one level deeper var initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope; @@ -55670,6 +62539,37 @@ function _markVariableAsUsed(scopeManager, currentNode, parserOptions, name) { return false; } +/** + * Runs a rule, and gets its listeners + * @param {Rule} rule A normalized rule with a `create` method + * @param {Context} ruleContext The context that should be passed to the rule + * @returns {Object} A map of selector listeners provided by the rule + */ +function createRuleListeners(rule, ruleContext) { + try { + return rule.create(ruleContext); + } catch (ex) { + ex.message = "Error while loading rule '" + ruleContext.id + "': " + ex.message; + throw ex; + } +} + +/** + * Gets all the ancestors of a given node + * @param {ASTNode} node The node + * @returns {ASTNode[]} All the ancestor nodes in the AST, not including the provided node, starting + * from the root node and going inwards to the parent node. + */ +function _getAncestors(node) { + var ancestorsStartingAtParent = []; + + for (var ancestor = node.parent; ancestor; ancestor = ancestor.parent) { + ancestorsStartingAtParent.push(ancestor); + } + + return ancestorsStartingAtParent.reverse(); +} + // methods that exist on SourceCode object var DEPRECATED_SOURCECODE_PASSTHROUGHS = { getSource: "getText", @@ -55696,13 +62596,132 @@ var DEPRECATED_SOURCECODE_PASSTHROUGHS = { var BASE_TRAVERSAL_CONTEXT = Object.freeze(Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).reduce(function (contextInfo, methodName) { return Object.assign(contextInfo, _defineProperty({}, methodName, function () { - var sourceCode = this.getSourceCode(); + var _getSourceCode; - return sourceCode[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]].apply(sourceCode, arguments); + return (_getSourceCode = this.getSourceCode())[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]].apply(_getSourceCode, arguments); })); }, {})); +/** + * Runs the given rules on the given SourceCode object + * @param {SourceCode} sourceCode A SourceCode object for the given text + * @param {Object} configuredRules The rules configuration + * @param {function(string): Rule} ruleMapper A mapper function from rule names to rules + * @param {Object} parserOptions The options that were passed to the parser + * @param {string} parserName The name of the parser in the config + * @param {Object} settings The settings that were enabled in the config + * @param {string} filename The reported filename of the code + * @returns {Problem[]} An array of reported problems + */ +function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename) { + var emitter = createEmitter(); + var nodeQueue = []; + var currentNode = sourceCode.ast; + + Traverser.traverse(sourceCode.ast, { + enter: function enter(node, parent) { + node.parent = parent; + nodeQueue.push({ isEntering: true, node: node }); + }, + leave: function leave(node) { + nodeQueue.push({ isEntering: false, node: node }); + }, + + visitorKeys: sourceCode.visitorKeys + }); + + /* + * Create a frozen object with the ruleContext properties and methods that are shared by all rules. + * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the + * properties once for each rule. + */ + var sharedTraversalContext = Object.freeze(Object.assign(Object.create(BASE_TRAVERSAL_CONTEXT), { + getAncestors: function getAncestors() { + return _getAncestors(currentNode); + }, + getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager), + getFilename: function getFilename() { + return filename; + }, + getScope: function getScope() { + return _getScope(sourceCode.scopeManager, currentNode); + }, + getSourceCode: function getSourceCode() { + return sourceCode; + }, + markVariableAsUsed: function markVariableAsUsed(name) { + return _markVariableAsUsed(sourceCode.scopeManager, currentNode, parserOptions, name); + }, + parserOptions: parserOptions, + parserPath: parserName, + parserServices: sourceCode.parserServices, + settings: settings + })); + + var lintingProblems = []; + + Object.keys(configuredRules).forEach(function (ruleId) { + var severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]); + + if (severity === 0) { + return; + } + + var rule = ruleMapper(ruleId); + var messageIds = rule.meta && rule.meta.messages; + var reportTranslator = null; + var ruleContext = Object.freeze(Object.assign(Object.create(sharedTraversalContext), { + id: ruleId, + options: getRuleOptions(configuredRules[ruleId]), + report: function report() { + + /* + * Create a report translator lazily. + * In a vast majority of cases, any given rule reports zero errors on a given + * piece of code. Creating a translator lazily avoids the performance cost of + * creating a new translator function for each rule that usually doesn't get + * called. + * + * Using lazy report translators improves end-to-end performance by about 3% + * with Node 8.4.0. + */ + if (reportTranslator === null) { + reportTranslator = createReportTranslator({ ruleId: ruleId, severity: severity, sourceCode: sourceCode, messageIds: messageIds }); + } + var problem = reportTranslator.apply(undefined, arguments); + + if (problem.fix && rule.meta && !rule.meta.fixable) { + throw new Error("Fixable rules should export a `meta.fixable` property."); + } + lintingProblems.push(problem); + } + })); + + var ruleListeners = createRuleListeners(rule, ruleContext); + + // add all the selectors from the rule as listeners + Object.keys(ruleListeners).forEach(function (selector) { + emitter.on(selector, timing.enabled ? timing.time(ruleId, ruleListeners[selector]) : ruleListeners[selector]); + }); + }); + + var eventGenerator = new CodePathAnalyzer(new NodeEventGenerator(emitter)); + + nodeQueue.forEach(function (traversalInfo) { + currentNode = traversalInfo.node; + + if (traversalInfo.isEntering) { + eventGenerator.enterNode(currentNode); + } else { + eventGenerator.leaveNode(currentNode); + } + }); + + return lintingProblems; +} + var lastSourceCodes = new WeakMap(); +var loadedParserMaps = new WeakMap(); //------------------------------------------------------------------------------ // Public Interface @@ -55717,58 +62736,56 @@ module.exports = function () { _classCallCheck(this, Linter); lastSourceCodes.set(this, null); + loadedParserMaps.set(this, new Map()); this.version = pkg.version; this.rules = new Rules(); - this._parsers = new Map(); this.environments = new Environments(); } /** - * Configuration object for the `verify` API. A JS representation of the eslintrc files. - * @typedef {Object} ESLintConfig - * @property {Object} rules The rule configuration to verify against. - * @property {string} [parser] Parser to use when generatig the AST. - * @property {Object} [parserOptions] Options for the parsed used. - * @property {Object} [settings] Global settings passed to each rule. - * @property {Object} [env] The environment to verify in. - * @property {Object} [globals] Available globals to the code. - */ - - /** - * Same as linter.verify, except without support for processors. - * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object. - * @param {ESLintConfig} config An ESLintConfig instance to configure everything. - * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked. - * If this is not set, the filename will default to '' in the rule context. If - * an object, then it has "filename", "saveState", and "allowInlineConfig" properties. - * @param {boolean} [filenameOrOptions.allowInlineConfig=true] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied. - * Useful if you want to validate JS without comments overriding rules. - * @param {boolean} [filenameOrOptions.reportUnusedDisableDirectives=false] Adds reported errors for unused - * eslint-disable directives - * @returns {Object[]} The results as an array of messages or null if no messages. + * Getter for package version. + * @static + * @returns {string} The version from package.json. */ _createClass(Linter, [{ key: "_verifyWithoutProcessors", - value: function _verifyWithoutProcessors(textOrSourceCode, config, filenameOrOptions) { + + + /** + * Configuration object for the `verify` API. A JS representation of the eslintrc files. + * @typedef {Object} ESLintConfig + * @property {Object} rules The rule configuration to verify against. + * @property {string} [parser] Parser to use when generatig the AST. + * @property {Object} [parserOptions] Options for the parsed used. + * @property {Object} [settings] Global settings passed to each rule. + * @property {Object} [env] The environment to verify in. + * @property {Object} [globals] Available globals to the code. + */ + + /** + * Same as linter.verify, except without support for processors. + * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object. + * @param {ESLintConfig} providedConfig An ESLintConfig instance to configure everything. + * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked. + * If this is not set, the filename will default to '' in the rule context. If + * an object, then it has "filename", "saveState", and "allowInlineConfig" properties. + * @param {boolean} [filenameOrOptions.allowInlineConfig=true] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied. + * Useful if you want to validate JS without comments overriding rules. + * @param {boolean} [filenameOrOptions.reportUnusedDisableDirectives=false] Adds reported errors for unused + * eslint-disable directives + * @returns {Object[]} The results as an array of messages or an empty array if no messages. + */ + value: function _verifyWithoutProcessors(textOrSourceCode, providedConfig, filenameOrOptions) { var _this = this; - var text = void 0, - allowInlineConfig = void 0, - providedFilename = void 0, - reportUnusedDisableDirectives = void 0; + var config = providedConfig || {}; + var options = normalizeVerifyOptions(filenameOrOptions); + var text = void 0; // evaluate arguments - if ((typeof filenameOrOptions === "undefined" ? "undefined" : _typeof(filenameOrOptions)) === "object") { - providedFilename = filenameOrOptions.filename; - allowInlineConfig = filenameOrOptions.allowInlineConfig; - reportUnusedDisableDirectives = filenameOrOptions.reportUnusedDisableDirectives; - } else { - providedFilename = filenameOrOptions; - } - if (typeof textOrSourceCode === "string") { lastSourceCodes.set(this, null); text = textOrSourceCode; @@ -55777,48 +62794,24 @@ module.exports = function () { text = textOrSourceCode.text; } - var filename = typeof providedFilename === "string" ? providedFilename : ""; - // search and apply "eslint-env *". var envInFile = findEslintEnv(text); + var resolvedEnvConfig = Object.assign({ builtin: true }, config.env, envInFile); + var enabledEnvs = Object.keys(resolvedEnvConfig).filter(function (envName) { + return resolvedEnvConfig[envName]; + }).map(function (envName) { + return _this.environments.get(envName); + }).filter(function (env) { + return env; + }); - config = Object.assign({}, config); - - if (envInFile) { - if (config.env) { - config.env = Object.assign({}, config.env, envInFile); - } else { - config.env = envInFile; - } - } - - // process initial config to make it safe to extend - config = prepareConfig(config, this.environments); + var parserName = config.parser || DEFAULT_PARSER_NAME; + var parserOptions = resolveParserOptions(parserName, config.parserOptions || {}, enabledEnvs); + var configuredGlobals = resolveGlobals(config.globals || {}, enabledEnvs); + var settings = config.settings || {}; if (!lastSourceCodes.get(this)) { - - // there's no input, just exit here - if (text.trim().length === 0) { - lastSourceCodes.set(this, new SourceCode(text, blankScriptAST)); - return []; - } - - var parser = void 0; - - try { - parser = this._parsers.get(config.parser) || require(config.parser); - } catch (ex) { - return [{ - ruleId: null, - fatal: true, - severity: 2, - source: null, - message: ex.message, - line: 0, - column: 0 - }]; - } - var parseResult = parse(text, config.parserOptions, parser, filename); + var parseResult = parse(text, parserOptions, parserName, loadedParserMaps.get(this), options.filename); if (!parseResult.success) { return [parseResult.error]; @@ -55839,170 +62832,42 @@ module.exports = function () { ast: lastSourceCode.ast, parserServices: lastSourceCode.parserServices, visitorKeys: lastSourceCode.visitorKeys, - scopeManager: analyzeScope(lastSourceCode.ast, config.parserOptions) + scopeManager: analyzeScope(lastSourceCode.ast, parserOptions) })); } } - var problems = []; var sourceCode = lastSourceCodes.get(this); - var disableDirectives = void 0; - - // parse global comments and modify config - if (allowInlineConfig !== false) { - var modifyConfigResult = modifyConfigsFromComments(filename, sourceCode.ast, config, function (ruleId) { - return _this.rules.get(ruleId); - }); - - config = modifyConfigResult.config; - modifyConfigResult.problems.forEach(function (problem) { - return problems.push(problem); - }); - disableDirectives = modifyConfigResult.disableDirectives; - } else { - disableDirectives = []; - } - - var emitter = createEmitter(); - var traverser = new Traverser(); - var scopeManager = sourceCode.scopeManager; - - /* - * Create a frozen object with the ruleContext properties and methods that are shared by all rules. - * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the - * properties once for each rule. - */ - var sharedTraversalContext = Object.freeze(Object.assign(Object.create(BASE_TRAVERSAL_CONTEXT), { - getAncestors: function getAncestors() { - return traverser.parents(); - }, - getDeclaredVariables: scopeManager.getDeclaredVariables.bind(scopeManager), - getFilename: function getFilename() { - return filename; - }, - getScope: function getScope() { - return _getScope(scopeManager, traverser.current(), config.parserOptions.ecmaVersion); - }, - getSourceCode: function getSourceCode() { - return sourceCode; - }, - markVariableAsUsed: function markVariableAsUsed(name) { - return _markVariableAsUsed(scopeManager, traverser.current(), config.parserOptions, name); - }, - parserOptions: config.parserOptions, - parserPath: config.parser, - parserServices: sourceCode.parserServices, - settings: config.settings, - - /** - * This is used to avoid breaking rules that used to monkeypatch the `Linter#report` method - * by using the `_linter` property on rule contexts. - * - * This should be removed in a major release after we create a better way to - * lint for unused disable comments. - * https://github.com/eslint/eslint/issues/9193 - */ - _linter: { - report: function report() {}, - - on: emitter.on - } - })); - - // enable appropriate rules - Object.keys(config.rules).forEach(function (ruleId) { - var severity = ConfigOps.getRuleSeverity(config.rules[ruleId]); - - if (severity === 0) { - return; - } - - var rule = _this.rules.get(ruleId); - var messageIds = rule && rule.meta && rule.meta.messages; - var reportTranslator = null; - var ruleContext = Object.freeze(Object.assign(Object.create(sharedTraversalContext), { - id: ruleId, - options: getRuleOptions(config.rules[ruleId]), - report: function report() { - - /* - * Create a report translator lazily. - * In a vast majority of cases, any given rule reports zero errors on a given - * piece of code. Creating a translator lazily avoids the performance cost of - * creating a new translator function for each rule that usually doesn't get - * called. - * - * Using lazy report translators improves end-to-end performance by about 3% - * with Node 8.4.0. - */ - if (reportTranslator === null) { - reportTranslator = createReportTranslator({ ruleId: ruleId, severity: severity, sourceCode: sourceCode, messageIds: messageIds }); - } - var problem = reportTranslator.apply(null, arguments); - - if (problem.fix && rule.meta && !rule.meta.fixable) { - throw new Error("Fixable rules should export a `meta.fixable` property."); - } - problems.push(problem); - - /* - * This is used to avoid breaking rules that used monkeypatch Linter, and relied on - * `linter.report` getting called with report info every time a rule reports a problem. - * To continue to support this, make sure that `context._linter.report` is called every - * time a problem is reported by a rule, even though `context._linter` is no longer a - * `Linter` instance. - * - * This should be removed in a major release after we create a better way to - * lint for unused disable comments. - * https://github.com/eslint/eslint/issues/9193 - */ - sharedTraversalContext._linter.report( // eslint-disable-line no-underscore-dangle - problem.ruleId, problem.severity, { loc: { start: { line: problem.line, column: problem.column - 1 } } }, problem.message); - } - })); - - try { - var ruleListeners = rule.create(ruleContext); - - // add all the selectors from the rule as listeners - Object.keys(ruleListeners).forEach(function (selector) { - emitter.on(selector, timing.enabled ? timing.time(ruleId, ruleListeners[selector]) : ruleListeners[selector]); - }); - } catch (ex) { - ex.message = "Error while loading rule '" + ruleId + "': " + ex.message; - throw ex; - } - }); + var commentDirectives = options.allowInlineConfig ? getDirectiveComments(options.filename, sourceCode.ast, function (ruleId) { + return _this.rules.get(ruleId); + }) : { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] }; // augment global scope with declared global variables - addDeclaredGlobals(scopeManager.scopes[0], config, this.environments); + addDeclaredGlobals(sourceCode.scopeManager.scopes[0], configuredGlobals, { exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }); - var eventGenerator = new CodePathAnalyzer(new NodeEventGenerator(emitter)); + var configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules); - /* - * Each node has a type property. Whenever a particular type of - * node is found, an event is fired. This allows any listeners to - * automatically be informed that this type of node has been found - * and react accordingly. - */ - traverser.traverse(sourceCode.ast, { - enter: function enter(node, parent) { - node.parent = parent; - eventGenerator.enterNode(node); - }, - leave: function leave(node) { - eventGenerator.leaveNode(node); - }, + var lintingProblems = void 0; - visitorKeys: sourceCode.visitorKeys - }); + try { + lintingProblems = runRules(sourceCode, configuredRules, function (ruleId) { + return _this.rules.get(ruleId); + }, parserOptions, parserName, settings, options.filename); + } catch (err) { + debug("An error occurred while traversing"); + debug("Filename:", options.filename); + debug("Parser Options:", parserOptions); + debug("Parser Path:", parserName); + debug("Settings:", settings); + throw err; + } return applyDisableDirectives({ - directives: disableDirectives, - problems: problems.sort(function (problemA, problemB) { + directives: commentDirectives.disableDirectives, + problems: lintingProblems.concat(commentDirectives.problems).sort(function (problemA, problemB) { return problemA.line - problemB.line || problemA.column - problemB.column; }), - reportUnusedDisableDirectives: reportUnusedDisableDirectives + reportUnusedDisableDirectives: options.reportUnusedDisableDirectives }); } @@ -56013,8 +62878,6 @@ module.exports = function () { * @param {(string|Object)} [filenameOrOptions] The optional filename of the file being checked. * If this is not set, the filename will default to '' in the rule context. If * an object, then it has "filename", "saveState", and "allowInlineConfig" properties. - * @param {boolean} [saveState] Indicates if the state from the last run should be saved. - * Mostly useful for testing purposes. * @param {boolean} [filenameOrOptions.allowInlineConfig] Allow/disallow inline comments' ability to change config once it is set. Defaults to true if not supplied. * Useful if you want to validate JS without comments overriding rules. * @param {function(string): string[]} [filenameOrOptions.preprocess] preprocessor for source text. If provided, @@ -56022,7 +62885,7 @@ module.exports = function () { * @param {function(Array): Object[]} [filenameOrOptions.postprocess] postprocessor for report messages. If provided, * this should accept an array of the message lists for each code block returned from the preprocessor, * apply a mapping to the messages as appropriate, and return a one-dimensional array of messages - * @returns {Object[]} The results as an array of messages or null if no messages. + * @returns {Object[]} The results as an array of messages or an empty array if no messages. */ }, { @@ -56101,7 +62964,7 @@ module.exports = function () { }, { key: "defineParser", value: function defineParser(parserId, parserModule) { - this._parsers.set(parserId, parserModule); + loadedParserMaps.get(this).set(parserId, parserModule); } /** @@ -56129,7 +62992,8 @@ module.exports = function () { var messages = [], fixedResult = void 0, fixed = false, - passNumber = 0; + passNumber = 0, + currentText = text; var debugTextDescription = options && options.filename || text.slice(0, 10) + "..."; var shouldFix = options && typeof options.fix !== "undefined" ? options.fix : true; @@ -56146,10 +63010,10 @@ module.exports = function () { passNumber++; debug("Linting code for " + debugTextDescription + " (pass " + passNumber + ")"); - messages = this.verify(text, config, options); + messages = this.verify(currentText, config, options); debug("Generating fixed text for " + debugTextDescription + " (pass " + passNumber + ")"); - fixedResult = SourceCodeFixer.applyFixes(text, messages, shouldFix); + fixedResult = SourceCodeFixer.applyFixes(currentText, messages, shouldFix); /* * stop if there are any syntax errors. @@ -56163,7 +63027,7 @@ module.exports = function () { fixed = fixed || fixedResult.fixed; // update to use the fixed output instead of the original text - text = fixedResult.output; + currentText = fixedResult.output; } while (fixedResult.fixed && passNumber < MAX_AUTOFIX_PASSES); /* @@ -56171,21 +63035,26 @@ module.exports = function () { * the most up-to-date information. */ if (fixedResult.fixed) { - fixedResult.messages = this.verify(text, config, options); + fixedResult.messages = this.verify(currentText, config, options); } // ensure the last result properly reflects if fixes were done fixedResult.fixed = fixed; - fixedResult.output = text; + fixedResult.output = currentText; return fixedResult; } + }], [{ + key: "version", + get: function get() { + return pkg.version; + } }]); return Linter; }(); -},{"../conf/blank-script.json":1,"../conf/default-config-options.js":3,"../package.json":114,"./ast-utils":115,"./code-path-analysis/code-path-analyzer":116,"./config/config-ops":123,"./config/config-validator":124,"./config/environments":125,"./report-translator":128,"./rules":129,"./timing":387,"./util/apply-disable-directives":402,"./util/node-event-generator":406,"./util/safe-emitter":409,"./util/source-code":411,"./util/source-code-fixer":410,"./util/traverser":412,"debug":52,"eslint-scope":59,"eslint-visitor-keys":67,"levn":87,"lodash":89}],127:[function(require,module,exports){ +},{"../package.json":111,"./code-path-analysis/code-path-analyzer":112,"./config/config-ops":119,"./config/config-validator":120,"./config/environments":121,"./rules":124,"./util/apply-disable-directives":404,"./util/ast-utils":405,"./util/config-comment-parser":406,"./util/node-event-generator":410,"./util/report-translator":412,"./util/safe-emitter":414,"./util/source-code":416,"./util/source-code-fixer":415,"./util/timing":417,"./util/traverser":418,"debug":53,"eslint-scope":60,"eslint-visitor-keys":69,"lodash":92}],123:[function(require,module,exports){ "use strict"; module.exports = function () { @@ -56245,8 +63114,10 @@ module.exports = function () { rules["lines-around-comment"] = require("./rules/lines-around-comment"); rules["lines-around-directive"] = require("./rules/lines-around-directive"); rules["lines-between-class-members"] = require("./rules/lines-between-class-members"); + rules["max-classes-per-file"] = require("./rules/max-classes-per-file"); rules["max-depth"] = require("./rules/max-depth"); rules["max-len"] = require("./rules/max-len"); + rules["max-lines-per-function"] = require("./rules/max-lines-per-function"); rules["max-lines"] = require("./rules/max-lines"); rules["max-nested-callbacks"] = require("./rules/max-nested-callbacks"); rules["max-params"] = require("./rules/max-params"); @@ -56261,6 +63132,7 @@ module.exports = function () { rules["newline-per-chained-call"] = require("./rules/newline-per-chained-call"); rules["no-alert"] = require("./rules/no-alert"); rules["no-array-constructor"] = require("./rules/no-array-constructor"); + rules["no-async-promise-executor"] = require("./rules/no-async-promise-executor"); rules["no-await-in-loop"] = require("./rules/no-await-in-loop"); rules["no-bitwise"] = require("./rules/no-bitwise"); rules["no-buffer-constructor"] = require("./rules/no-buffer-constructor"); @@ -56317,6 +63189,7 @@ module.exports = function () { rules["no-lonely-if"] = require("./rules/no-lonely-if"); rules["no-loop-func"] = require("./rules/no-loop-func"); rules["no-magic-numbers"] = require("./rules/no-magic-numbers"); + rules["no-misleading-character-class"] = require("./rules/no-misleading-character-class"); rules["no-mixed-operators"] = require("./rules/no-mixed-operators"); rules["no-mixed-requires"] = require("./rules/no-mixed-requires"); rules["no-mixed-spaces-and-tabs"] = require("./rules/no-mixed-spaces-and-tabs"); @@ -56383,6 +63256,7 @@ module.exports = function () { rules["no-unused-vars"] = require("./rules/no-unused-vars"); rules["no-use-before-define"] = require("./rules/no-use-before-define"); rules["no-useless-call"] = require("./rules/no-useless-call"); + rules["no-useless-catch"] = require("./rules/no-useless-catch"); rules["no-useless-computed-key"] = require("./rules/no-useless-computed-key"); rules["no-useless-concat"] = require("./rules/no-useless-concat"); rules["no-useless-constructor"] = require("./rules/no-useless-constructor"); @@ -56409,6 +63283,7 @@ module.exports = function () { rules["prefer-const"] = require("./rules/prefer-const"); rules["prefer-destructuring"] = require("./rules/prefer-destructuring"); rules["prefer-numeric-literals"] = require("./rules/prefer-numeric-literals"); + rules["prefer-object-spread"] = require("./rules/prefer-object-spread"); rules["prefer-promise-reject-errors"] = require("./rules/prefer-promise-reject-errors"); rules["prefer-reflect"] = require("./rules/prefer-reflect"); rules["prefer-rest-params"] = require("./rules/prefer-rest-params"); @@ -56417,8 +63292,10 @@ module.exports = function () { rules["quote-props"] = require("./rules/quote-props"); rules["quotes"] = require("./rules/quotes"); rules["radix"] = require("./rules/radix"); + rules["require-atomic-updates"] = require("./rules/require-atomic-updates"); rules["require-await"] = require("./rules/require-await"); rules["require-jsdoc"] = require("./rules/require-jsdoc"); + rules["require-unicode-regexp"] = require("./rules/require-unicode-regexp"); rules["require-yield"] = require("./rules/require-yield"); rules["rest-spread-spacing"] = require("./rules/rest-spread-spacing"); rules["semi-spacing"] = require("./rules/semi-spacing"); @@ -56451,318 +63328,7 @@ module.exports = function () { return rules; }; -},{"./rules/accessor-pairs":130,"./rules/array-bracket-newline":131,"./rules/array-bracket-spacing":132,"./rules/array-callback-return":133,"./rules/array-element-newline":134,"./rules/arrow-body-style":135,"./rules/arrow-parens":136,"./rules/arrow-spacing":137,"./rules/block-scoped-var":138,"./rules/block-spacing":139,"./rules/brace-style":140,"./rules/callback-return":141,"./rules/camelcase":142,"./rules/capitalized-comments":143,"./rules/class-methods-use-this":144,"./rules/comma-dangle":145,"./rules/comma-spacing":146,"./rules/comma-style":147,"./rules/complexity":148,"./rules/computed-property-spacing":149,"./rules/consistent-return":150,"./rules/consistent-this":151,"./rules/constructor-super":152,"./rules/curly":153,"./rules/default-case":154,"./rules/dot-location":155,"./rules/dot-notation":156,"./rules/eol-last":157,"./rules/eqeqeq":158,"./rules/for-direction":159,"./rules/func-call-spacing":160,"./rules/func-name-matching":161,"./rules/func-names":162,"./rules/func-style":163,"./rules/function-paren-newline":164,"./rules/generator-star-spacing":165,"./rules/getter-return":166,"./rules/global-require":167,"./rules/guard-for-in":168,"./rules/handle-callback-err":169,"./rules/id-blacklist":170,"./rules/id-length":171,"./rules/id-match":172,"./rules/implicit-arrow-linebreak":173,"./rules/indent":175,"./rules/indent-legacy":174,"./rules/init-declarations":176,"./rules/jsx-quotes":177,"./rules/key-spacing":178,"./rules/keyword-spacing":179,"./rules/line-comment-position":180,"./rules/linebreak-style":181,"./rules/lines-around-comment":182,"./rules/lines-around-directive":183,"./rules/lines-between-class-members":184,"./rules/max-depth":185,"./rules/max-len":186,"./rules/max-lines":187,"./rules/max-nested-callbacks":188,"./rules/max-params":189,"./rules/max-statements":191,"./rules/max-statements-per-line":190,"./rules/multiline-comment-style":192,"./rules/multiline-ternary":193,"./rules/new-cap":194,"./rules/new-parens":195,"./rules/newline-after-var":196,"./rules/newline-before-return":197,"./rules/newline-per-chained-call":198,"./rules/no-alert":199,"./rules/no-array-constructor":200,"./rules/no-await-in-loop":201,"./rules/no-bitwise":202,"./rules/no-buffer-constructor":203,"./rules/no-caller":204,"./rules/no-case-declarations":205,"./rules/no-catch-shadow":206,"./rules/no-class-assign":207,"./rules/no-compare-neg-zero":208,"./rules/no-cond-assign":209,"./rules/no-confusing-arrow":210,"./rules/no-console":211,"./rules/no-const-assign":212,"./rules/no-constant-condition":213,"./rules/no-continue":214,"./rules/no-control-regex":215,"./rules/no-debugger":216,"./rules/no-delete-var":217,"./rules/no-div-regex":218,"./rules/no-dupe-args":219,"./rules/no-dupe-class-members":220,"./rules/no-dupe-keys":221,"./rules/no-duplicate-case":222,"./rules/no-duplicate-imports":223,"./rules/no-else-return":224,"./rules/no-empty":228,"./rules/no-empty-character-class":225,"./rules/no-empty-function":226,"./rules/no-empty-pattern":227,"./rules/no-eq-null":229,"./rules/no-eval":230,"./rules/no-ex-assign":231,"./rules/no-extend-native":232,"./rules/no-extra-bind":233,"./rules/no-extra-boolean-cast":234,"./rules/no-extra-label":235,"./rules/no-extra-parens":236,"./rules/no-extra-semi":237,"./rules/no-fallthrough":238,"./rules/no-floating-decimal":239,"./rules/no-func-assign":240,"./rules/no-global-assign":241,"./rules/no-implicit-coercion":242,"./rules/no-implicit-globals":243,"./rules/no-implied-eval":244,"./rules/no-inline-comments":245,"./rules/no-inner-declarations":246,"./rules/no-invalid-regexp":247,"./rules/no-invalid-this":248,"./rules/no-irregular-whitespace":249,"./rules/no-iterator":250,"./rules/no-label-var":251,"./rules/no-labels":252,"./rules/no-lone-blocks":253,"./rules/no-lonely-if":254,"./rules/no-loop-func":255,"./rules/no-magic-numbers":256,"./rules/no-mixed-operators":257,"./rules/no-mixed-requires":258,"./rules/no-mixed-spaces-and-tabs":259,"./rules/no-multi-assign":260,"./rules/no-multi-spaces":261,"./rules/no-multi-str":262,"./rules/no-multiple-empty-lines":263,"./rules/no-native-reassign":264,"./rules/no-negated-condition":265,"./rules/no-negated-in-lhs":266,"./rules/no-nested-ternary":267,"./rules/no-new":273,"./rules/no-new-func":268,"./rules/no-new-object":269,"./rules/no-new-require":270,"./rules/no-new-symbol":271,"./rules/no-new-wrappers":272,"./rules/no-obj-calls":274,"./rules/no-octal":276,"./rules/no-octal-escape":275,"./rules/no-param-reassign":277,"./rules/no-path-concat":278,"./rules/no-plusplus":279,"./rules/no-process-env":280,"./rules/no-process-exit":281,"./rules/no-proto":282,"./rules/no-prototype-builtins":283,"./rules/no-redeclare":284,"./rules/no-regex-spaces":285,"./rules/no-restricted-globals":286,"./rules/no-restricted-imports":287,"./rules/no-restricted-modules":288,"./rules/no-restricted-properties":289,"./rules/no-restricted-syntax":290,"./rules/no-return-assign":291,"./rules/no-return-await":292,"./rules/no-script-url":293,"./rules/no-self-assign":294,"./rules/no-self-compare":295,"./rules/no-sequences":296,"./rules/no-shadow":298,"./rules/no-shadow-restricted-names":297,"./rules/no-spaced-func":299,"./rules/no-sparse-arrays":300,"./rules/no-sync":301,"./rules/no-tabs":302,"./rules/no-template-curly-in-string":303,"./rules/no-ternary":304,"./rules/no-this-before-super":305,"./rules/no-throw-literal":306,"./rules/no-trailing-spaces":307,"./rules/no-undef":309,"./rules/no-undef-init":308,"./rules/no-undefined":310,"./rules/no-underscore-dangle":311,"./rules/no-unexpected-multiline":312,"./rules/no-unmodified-loop-condition":313,"./rules/no-unneeded-ternary":314,"./rules/no-unreachable":315,"./rules/no-unsafe-finally":316,"./rules/no-unsafe-negation":317,"./rules/no-unused-expressions":318,"./rules/no-unused-labels":319,"./rules/no-unused-vars":320,"./rules/no-use-before-define":321,"./rules/no-useless-call":322,"./rules/no-useless-computed-key":323,"./rules/no-useless-concat":324,"./rules/no-useless-constructor":325,"./rules/no-useless-escape":326,"./rules/no-useless-rename":327,"./rules/no-useless-return":328,"./rules/no-var":329,"./rules/no-void":330,"./rules/no-warning-comments":331,"./rules/no-whitespace-before-property":332,"./rules/no-with":333,"./rules/nonblock-statement-body-position":334,"./rules/object-curly-newline":335,"./rules/object-curly-spacing":336,"./rules/object-property-newline":337,"./rules/object-shorthand":338,"./rules/one-var":340,"./rules/one-var-declaration-per-line":339,"./rules/operator-assignment":341,"./rules/operator-linebreak":342,"./rules/padded-blocks":343,"./rules/padding-line-between-statements":344,"./rules/prefer-arrow-callback":345,"./rules/prefer-const":346,"./rules/prefer-destructuring":347,"./rules/prefer-numeric-literals":348,"./rules/prefer-promise-reject-errors":349,"./rules/prefer-reflect":350,"./rules/prefer-rest-params":351,"./rules/prefer-spread":352,"./rules/prefer-template":353,"./rules/quote-props":354,"./rules/quotes":355,"./rules/radix":356,"./rules/require-await":357,"./rules/require-jsdoc":358,"./rules/require-yield":359,"./rules/rest-spread-spacing":360,"./rules/semi":363,"./rules/semi-spacing":361,"./rules/semi-style":362,"./rules/sort-imports":364,"./rules/sort-keys":365,"./rules/sort-vars":366,"./rules/space-before-blocks":367,"./rules/space-before-function-paren":368,"./rules/space-in-parens":369,"./rules/space-infix-ops":370,"./rules/space-unary-ops":371,"./rules/spaced-comment":372,"./rules/strict":373,"./rules/switch-colon-spacing":374,"./rules/symbol-description":375,"./rules/template-curly-spacing":376,"./rules/template-tag-spacing":377,"./rules/unicode-bom":378,"./rules/use-isnan":379,"./rules/valid-jsdoc":380,"./rules/valid-typeof":381,"./rules/vars-on-top":382,"./rules/wrap-iife":383,"./rules/wrap-regex":384,"./rules/yield-star-spacing":385,"./rules/yoda":386}],128:[function(require,module,exports){ -/** - * @fileoverview A helper that translates context.report() calls from the rule API into generic problem objects - * @author Teddy Katz - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var assert = require("assert"); -var ruleFixer = require("./util/rule-fixer"); -var interpolate = require("./util/interpolate"); - -//------------------------------------------------------------------------------ -// Typedefs -//------------------------------------------------------------------------------ - -/** - * An error message description - * @typedef {Object} MessageDescriptor - * @property {ASTNode} [node] The reported node - * @property {Location} loc The location of the problem. - * @property {string} message The problem message. - * @property {Object} [data] Optional data to use to fill in placeholders in the - * message. - * @property {Function} [fix] The function to call that creates a fix command. - */ - -/** - * Information about the report - * @typedef {Object} ReportInfo - * @property {string} ruleId - * @property {(0|1|2)} severity - * @property {(string|undefined)} message - * @property {(string|undefined)} messageId - * @property {number} line - * @property {number} column - * @property {(number|undefined)} endLine - * @property {(number|undefined)} endColumn - * @property {(string|null)} nodeType - * @property {string} source - * @property {({text: string, range: (number[]|null)}|null)} fix - */ - -//------------------------------------------------------------------------------ -// Module Definition -//------------------------------------------------------------------------------ - - -/** - * Translates a multi-argument context.report() call into a single object argument call - * @param {...*} arguments A list of arguments passed to `context.report` - * @returns {MessageDescriptor} A normalized object containing report information - */ -function normalizeMultiArgReportCall() { - - // If there is one argument, it is considered to be a new-style call already. - if (arguments.length === 1) { - - // Shallow clone the object to avoid surprises if reusing the descriptor - return Object.assign({}, arguments[0]); - } - - // If the second argument is a string, the arguments are interpreted as [node, message, data, fix]. - if (typeof arguments[1] === "string") { - return { - node: arguments[0], - message: arguments[1], - data: arguments[2], - fix: arguments[3] - }; - } - - // Otherwise, the arguments are interpreted as [node, loc, message, data, fix]. - return { - node: arguments[0], - loc: arguments[1], - message: arguments[2], - data: arguments[3], - fix: arguments[4] - }; -} - -/** - * Asserts that either a loc or a node was provided, and the node is valid if it was provided. - * @param {MessageDescriptor} descriptor A descriptor to validate - * @returns {void} - * @throws AssertionError if neither a node nor a loc was provided, or if the node is not an object - */ -function assertValidNodeInfo(descriptor) { - if (descriptor.node) { - assert(_typeof(descriptor.node) === "object", "Node must be an object"); - } else { - assert(descriptor.loc, "Node must be provided when reporting error if location is not provided"); - } -} - -/** - * Normalizes a MessageDescriptor to always have a `loc` with `start` and `end` properties - * @param {MessageDescriptor} descriptor A descriptor for the report from a rule. - * @returns {{start: Location, end: (Location|null)}} An updated location that infers the `start` and `end` properties - * from the `node` of the original descriptor, or infers the `start` from the `loc` of the original descriptor. - */ -function normalizeReportLoc(descriptor) { - if (descriptor.loc) { - if (descriptor.loc.start) { - return descriptor.loc; - } - return { start: descriptor.loc, end: null }; - } - return descriptor.node.loc; -} - -/** - * Interpolates data placeholders in report messages - * @param {MessageDescriptor} descriptor The report message descriptor. - * @returns {string} The interpolated message for the descriptor - */ -function normalizeMessagePlaceholders(descriptor) { - return interpolate(descriptor.message, descriptor.data); -} - -/** - * Compares items in a fixes array by range. - * @param {Fix} a The first message. - * @param {Fix} b The second message. - * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. - * @private - */ -function compareFixesByRange(a, b) { - return a.range[0] - b.range[0] || a.range[1] - b.range[1]; -} - -/** - * Merges the given fixes array into one. - * @param {Fix[]} fixes The fixes to merge. - * @param {SourceCode} sourceCode The source code object to get the text between fixes. - * @returns {{text: string, range: number[]}} The merged fixes - */ -function mergeFixes(fixes, sourceCode) { - if (fixes.length === 0) { - return null; - } - if (fixes.length === 1) { - return fixes[0]; - } - - fixes.sort(compareFixesByRange); - - var originalText = sourceCode.text; - var start = fixes[0].range[0]; - var end = fixes[fixes.length - 1].range[1]; - var text = ""; - var lastPos = Number.MIN_SAFE_INTEGER; - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = fixes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var fix = _step.value; - - assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); - - if (fix.range[0] >= 0) { - text += originalText.slice(Math.max(0, start, lastPos), fix.range[0]); - } - text += fix.text; - lastPos = fix.range[1]; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - text += originalText.slice(Math.max(0, start, lastPos), end); - - return { range: [start, end], text: text }; -} - -/** - * Gets one fix object from the given descriptor. - * If the descriptor retrieves multiple fixes, this merges those to one. - * @param {MessageDescriptor} descriptor The report descriptor. - * @param {SourceCode} sourceCode The source code object to get text between fixes. - * @returns {({text: string, range: number[]}|null)} The fix for the descriptor - */ -function normalizeFixes(descriptor, sourceCode) { - if (typeof descriptor.fix !== "function") { - return null; - } - - // @type {null | Fix | Fix[] | IterableIterator} - var fix = descriptor.fix(ruleFixer); - - // Merge to one. - if (fix && Symbol.iterator in fix) { - return mergeFixes(Array.from(fix), sourceCode); - } - return fix; -} - -/** - * Creates information about the report from a descriptor - * @param {Object} options Information about the problem - * @param {string} options.ruleId Rule ID - * @param {(0|1|2)} options.severity Rule severity - * @param {(ASTNode|null)} options.node Node - * @param {string} options.message Error message - * @param {{start: SourceLocation, end: (SourceLocation|null)}} options.loc Start and end location - * @param {{text: string, range: (number[]|null)}} options.fix The fix object - * @param {string[]} options.sourceLines Source lines - * @returns {function(...args): ReportInfo} Function that returns information about the report - */ -function createProblem(options) { - var problem = { - ruleId: options.ruleId, - severity: options.severity, - message: options.message, - line: options.loc.start.line, - column: options.loc.start.column + 1, - nodeType: options.node && options.node.type || null, - source: options.sourceLines[options.loc.start.line - 1] || "" - }; - - /* - * If this isn’t in the conditional, some of the tests fail - * because `messageId` is present in the problem object - */ - if (options.messageId) { - problem.messageId = options.messageId; - } - - if (options.loc.end) { - problem.endLine = options.loc.end.line; - problem.endColumn = options.loc.end.column + 1; - } - - if (options.fix) { - problem.fix = options.fix; - } - - return problem; -} - -/** - * Returns a function that converts the arguments of a `context.report` call from a rule into a reported - * problem for the Node.js API. - * @param {{ruleId: string, severity: number, sourceCode: SourceCode, messageIds: Object}} metadata Metadata for the reported problem - * @param {SourceCode} sourceCode The `SourceCode` instance for the text being linted - * @returns {function(...args): ReportInfo} Function that returns information about the report - */ - -module.exports = function createReportTranslator(metadata) { - - /* - * `createReportTranslator` gets called once per enabled rule per file. It needs to be very performant. - * The report translator itself (i.e. the function that `createReportTranslator` returns) gets - * called every time a rule reports a problem, which happens much less frequently (usually, the vast - * majority of rules don't report any problems for a given file). - */ - return function () { - var descriptor = normalizeMultiArgReportCall.apply(null, arguments); - - assertValidNodeInfo(descriptor); - - if (descriptor.messageId) { - if (!metadata.messageIds) { - throw new TypeError("context.report() called with a messageId, but no messages were present in the rule metadata."); - } - var id = descriptor.messageId; - var messages = metadata.messageIds; - - if (descriptor.message) { - throw new TypeError("context.report() called with a message and a messageId. Please only pass one."); - } - if (!messages || !Object.prototype.hasOwnProperty.call(messages, id)) { - throw new TypeError("context.report() called with a messageId of '" + id + "' which is not present in the 'messages' config: " + JSON.stringify(messages, null, 2)); - } - descriptor.message = messages[id]; - } - - return createProblem({ - ruleId: metadata.ruleId, - severity: metadata.severity, - node: descriptor.node, - message: normalizeMessagePlaceholders(descriptor), - messageId: descriptor.messageId, - loc: normalizeReportLoc(descriptor), - fix: normalizeFixes(descriptor, metadata.sourceCode), - sourceLines: metadata.sourceCode.lines - }); - }; -}; - -},{"./util/interpolate":404,"./util/rule-fixer":408,"assert":47}],129:[function(require,module,exports){ +},{"./rules/accessor-pairs":125,"./rules/array-bracket-newline":126,"./rules/array-bracket-spacing":127,"./rules/array-callback-return":128,"./rules/array-element-newline":129,"./rules/arrow-body-style":130,"./rules/arrow-parens":131,"./rules/arrow-spacing":132,"./rules/block-scoped-var":133,"./rules/block-spacing":134,"./rules/brace-style":135,"./rules/callback-return":136,"./rules/camelcase":137,"./rules/capitalized-comments":138,"./rules/class-methods-use-this":139,"./rules/comma-dangle":140,"./rules/comma-spacing":141,"./rules/comma-style":142,"./rules/complexity":143,"./rules/computed-property-spacing":144,"./rules/consistent-return":145,"./rules/consistent-this":146,"./rules/constructor-super":147,"./rules/curly":148,"./rules/default-case":149,"./rules/dot-location":150,"./rules/dot-notation":151,"./rules/eol-last":152,"./rules/eqeqeq":153,"./rules/for-direction":154,"./rules/func-call-spacing":155,"./rules/func-name-matching":156,"./rules/func-names":157,"./rules/func-style":158,"./rules/function-paren-newline":159,"./rules/generator-star-spacing":160,"./rules/getter-return":161,"./rules/global-require":162,"./rules/guard-for-in":163,"./rules/handle-callback-err":164,"./rules/id-blacklist":165,"./rules/id-length":166,"./rules/id-match":167,"./rules/implicit-arrow-linebreak":168,"./rules/indent":170,"./rules/indent-legacy":169,"./rules/init-declarations":171,"./rules/jsx-quotes":172,"./rules/key-spacing":173,"./rules/keyword-spacing":174,"./rules/line-comment-position":175,"./rules/linebreak-style":176,"./rules/lines-around-comment":177,"./rules/lines-around-directive":178,"./rules/lines-between-class-members":179,"./rules/max-classes-per-file":180,"./rules/max-depth":181,"./rules/max-len":182,"./rules/max-lines":184,"./rules/max-lines-per-function":183,"./rules/max-nested-callbacks":185,"./rules/max-params":186,"./rules/max-statements":188,"./rules/max-statements-per-line":187,"./rules/multiline-comment-style":189,"./rules/multiline-ternary":190,"./rules/new-cap":191,"./rules/new-parens":192,"./rules/newline-after-var":193,"./rules/newline-before-return":194,"./rules/newline-per-chained-call":195,"./rules/no-alert":196,"./rules/no-array-constructor":197,"./rules/no-async-promise-executor":198,"./rules/no-await-in-loop":199,"./rules/no-bitwise":200,"./rules/no-buffer-constructor":201,"./rules/no-caller":202,"./rules/no-case-declarations":203,"./rules/no-catch-shadow":204,"./rules/no-class-assign":205,"./rules/no-compare-neg-zero":206,"./rules/no-cond-assign":207,"./rules/no-confusing-arrow":208,"./rules/no-console":209,"./rules/no-const-assign":210,"./rules/no-constant-condition":211,"./rules/no-continue":212,"./rules/no-control-regex":213,"./rules/no-debugger":214,"./rules/no-delete-var":215,"./rules/no-div-regex":216,"./rules/no-dupe-args":217,"./rules/no-dupe-class-members":218,"./rules/no-dupe-keys":219,"./rules/no-duplicate-case":220,"./rules/no-duplicate-imports":221,"./rules/no-else-return":222,"./rules/no-empty":226,"./rules/no-empty-character-class":223,"./rules/no-empty-function":224,"./rules/no-empty-pattern":225,"./rules/no-eq-null":227,"./rules/no-eval":228,"./rules/no-ex-assign":229,"./rules/no-extend-native":230,"./rules/no-extra-bind":231,"./rules/no-extra-boolean-cast":232,"./rules/no-extra-label":233,"./rules/no-extra-parens":234,"./rules/no-extra-semi":235,"./rules/no-fallthrough":236,"./rules/no-floating-decimal":237,"./rules/no-func-assign":238,"./rules/no-global-assign":239,"./rules/no-implicit-coercion":240,"./rules/no-implicit-globals":241,"./rules/no-implied-eval":242,"./rules/no-inline-comments":243,"./rules/no-inner-declarations":244,"./rules/no-invalid-regexp":245,"./rules/no-invalid-this":246,"./rules/no-irregular-whitespace":247,"./rules/no-iterator":248,"./rules/no-label-var":249,"./rules/no-labels":250,"./rules/no-lone-blocks":251,"./rules/no-lonely-if":252,"./rules/no-loop-func":253,"./rules/no-magic-numbers":254,"./rules/no-misleading-character-class":255,"./rules/no-mixed-operators":256,"./rules/no-mixed-requires":257,"./rules/no-mixed-spaces-and-tabs":258,"./rules/no-multi-assign":259,"./rules/no-multi-spaces":260,"./rules/no-multi-str":261,"./rules/no-multiple-empty-lines":262,"./rules/no-native-reassign":263,"./rules/no-negated-condition":264,"./rules/no-negated-in-lhs":265,"./rules/no-nested-ternary":266,"./rules/no-new":272,"./rules/no-new-func":267,"./rules/no-new-object":268,"./rules/no-new-require":269,"./rules/no-new-symbol":270,"./rules/no-new-wrappers":271,"./rules/no-obj-calls":273,"./rules/no-octal":275,"./rules/no-octal-escape":274,"./rules/no-param-reassign":276,"./rules/no-path-concat":277,"./rules/no-plusplus":278,"./rules/no-process-env":279,"./rules/no-process-exit":280,"./rules/no-proto":281,"./rules/no-prototype-builtins":282,"./rules/no-redeclare":283,"./rules/no-regex-spaces":284,"./rules/no-restricted-globals":285,"./rules/no-restricted-imports":286,"./rules/no-restricted-modules":287,"./rules/no-restricted-properties":288,"./rules/no-restricted-syntax":289,"./rules/no-return-assign":290,"./rules/no-return-await":291,"./rules/no-script-url":292,"./rules/no-self-assign":293,"./rules/no-self-compare":294,"./rules/no-sequences":295,"./rules/no-shadow":297,"./rules/no-shadow-restricted-names":296,"./rules/no-spaced-func":298,"./rules/no-sparse-arrays":299,"./rules/no-sync":300,"./rules/no-tabs":301,"./rules/no-template-curly-in-string":302,"./rules/no-ternary":303,"./rules/no-this-before-super":304,"./rules/no-throw-literal":305,"./rules/no-trailing-spaces":306,"./rules/no-undef":308,"./rules/no-undef-init":307,"./rules/no-undefined":309,"./rules/no-underscore-dangle":310,"./rules/no-unexpected-multiline":311,"./rules/no-unmodified-loop-condition":312,"./rules/no-unneeded-ternary":313,"./rules/no-unreachable":314,"./rules/no-unsafe-finally":315,"./rules/no-unsafe-negation":316,"./rules/no-unused-expressions":317,"./rules/no-unused-labels":318,"./rules/no-unused-vars":319,"./rules/no-use-before-define":320,"./rules/no-useless-call":321,"./rules/no-useless-catch":322,"./rules/no-useless-computed-key":323,"./rules/no-useless-concat":324,"./rules/no-useless-constructor":325,"./rules/no-useless-escape":326,"./rules/no-useless-rename":327,"./rules/no-useless-return":328,"./rules/no-var":329,"./rules/no-void":330,"./rules/no-warning-comments":331,"./rules/no-whitespace-before-property":332,"./rules/no-with":333,"./rules/nonblock-statement-body-position":334,"./rules/object-curly-newline":335,"./rules/object-curly-spacing":336,"./rules/object-property-newline":337,"./rules/object-shorthand":338,"./rules/one-var":340,"./rules/one-var-declaration-per-line":339,"./rules/operator-assignment":341,"./rules/operator-linebreak":342,"./rules/padded-blocks":343,"./rules/padding-line-between-statements":344,"./rules/prefer-arrow-callback":345,"./rules/prefer-const":346,"./rules/prefer-destructuring":347,"./rules/prefer-numeric-literals":348,"./rules/prefer-object-spread":349,"./rules/prefer-promise-reject-errors":350,"./rules/prefer-reflect":351,"./rules/prefer-rest-params":352,"./rules/prefer-spread":353,"./rules/prefer-template":354,"./rules/quote-props":355,"./rules/quotes":356,"./rules/radix":357,"./rules/require-atomic-updates":358,"./rules/require-await":359,"./rules/require-jsdoc":360,"./rules/require-unicode-regexp":361,"./rules/require-yield":362,"./rules/rest-spread-spacing":363,"./rules/semi":366,"./rules/semi-spacing":364,"./rules/semi-style":365,"./rules/sort-imports":367,"./rules/sort-keys":368,"./rules/sort-vars":369,"./rules/space-before-blocks":370,"./rules/space-before-function-paren":371,"./rules/space-in-parens":372,"./rules/space-infix-ops":373,"./rules/space-unary-ops":374,"./rules/spaced-comment":375,"./rules/strict":376,"./rules/switch-colon-spacing":377,"./rules/symbol-description":378,"./rules/template-curly-spacing":379,"./rules/template-tag-spacing":380,"./rules/unicode-bom":381,"./rules/use-isnan":382,"./rules/valid-jsdoc":383,"./rules/valid-typeof":384,"./rules/vars-on-top":385,"./rules/wrap-iife":386,"./rules/wrap-regex":387,"./rules/yield-star-spacing":388,"./rules/yoda":389}],124:[function(require,module,exports){ /** * @fileoverview Defines a storage for rules. * @author Nicholas C. Zakas @@ -56934,7 +63500,7 @@ var Rules = function () { module.exports = Rules; -},{"../conf/replacements":5,"./load-rules":127,"lodash":89}],130:[function(require,module,exports){ +},{"../conf/replacements":3,"./load-rules":123,"lodash":92}],125:[function(require,module,exports){ /** * @fileoverview Rule to flag wrapping non-iife in parens * @author Gyandeep Singh @@ -56987,9 +63553,9 @@ function isPropertyDescriptor(node) { * Object.defineProperties(obj, {foo: {set: ...}}) * Object.create(proto, {foo: {set: ...}}) */ - node = node.parent.parent; + var grandparent = node.parent.parent; - return node.type === "ObjectExpression" && (isArgumentOfMethodCall(node, 1, "Object", "create") || isArgumentOfMethodCall(node, 1, "Object", "defineProperties")); + return grandparent.type === "ObjectExpression" && (isArgumentOfMethodCall(grandparent, 1, "Object", "create") || isArgumentOfMethodCall(grandparent, 1, "Object", "defineProperties")); } //------------------------------------------------------------------------------ @@ -56998,12 +63564,15 @@ function isPropertyDescriptor(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce getter and setter pairs in objects", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/accessor-pairs" }, + schema: [{ type: "object", properties: { @@ -57016,6 +63585,7 @@ module.exports = { }, additionalProperties: false }], + messages: { getter: "Getter is not present.", setter: "Setter is not present." @@ -57086,7 +63656,7 @@ module.exports = { } }; -},{}],131:[function(require,module,exports){ +},{}],126:[function(require,module,exports){ /** * @fileoverview Rule to enforce linebreaks after open and before close array brackets * @author Jan Peer Stöcklmair @@ -57094,7 +63664,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -57102,13 +63672,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce linebreaks after opening and before closing array brackets", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/array-bracket-newline" }, + fixable: "whitespace", + schema: [{ oneOf: [{ enum: ["always", "never", "consistent"] @@ -57126,6 +63700,7 @@ module.exports = { additionalProperties: false }] }], + messages: { unexpectedOpeningLinebreak: "There should be no linebreak after '['.", unexpectedClosingLinebreak: "There should be no linebreak before ']'.", @@ -57321,14 +63896,14 @@ module.exports = { } }; -},{"../ast-utils":115}],132:[function(require,module,exports){ +},{"../util/ast-utils":405}],127:[function(require,module,exports){ /** * @fileoverview Disallows or enforces spaces inside of array brackets. * @author Jamund Ferguson */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -57336,13 +63911,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing inside array brackets", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/array-bracket-spacing" }, + fixable: "whitespace", + schema: [{ enum: ["always", "never"] }, { @@ -57360,6 +63939,7 @@ module.exports = { }, additionalProperties: false }], + messages: { unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.", unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.", @@ -57546,7 +64126,7 @@ module.exports = { } }; -},{"../ast-utils":115}],133:[function(require,module,exports){ +},{"../util/ast-utils":405}],128:[function(require,module,exports){ /** * @fileoverview Rule to enforce return statements in callbacks of array's methods * @author Toru Nagashima @@ -57560,7 +64140,7 @@ module.exports = { var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -57617,8 +64197,10 @@ function isTargetMethod(node) { * @returns {boolean} `true` if the node is the callback of an array method. */ function isCallbackOfArrayMethod(node) { - while (node) { - var parent = node.parent; + var currentNode = node; + + while (currentNode) { + var parent = currentNode.parent; switch (parent.type) { @@ -57628,7 +64210,7 @@ function isCallbackOfArrayMethod(node) { */ case "LogicalExpression": case "ConditionalExpression": - node = parent; + currentNode = parent; break; /* @@ -57646,7 +64228,7 @@ function isCallbackOfArrayMethod(node) { if (func === null || !astUtils.isCallee(func)) { return false; } - node = func.parent; + currentNode = func.parent; break; } @@ -57657,10 +64239,10 @@ function isCallbackOfArrayMethod(node) { */ case "CallExpression": if (astUtils.isArrayFromMethod(parent.callee)) { - return parent.arguments.length >= 2 && parent.arguments[1] === node; + return parent.arguments.length >= 2 && parent.arguments[1] === currentNode; } if (isTargetMethod(parent.callee)) { - return parent.arguments.length >= 1 && parent.arguments[0] === node; + return parent.arguments.length >= 1 && parent.arguments[0] === currentNode; } return false; @@ -57680,6 +64262,8 @@ function isCallbackOfArrayMethod(node) { module.exports = { meta: { + type: "problem", + docs: { description: "enforce `return` statements in callbacks of array methods", category: "Best Practices", @@ -57785,7 +64369,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],134:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],129:[function(require,module,exports){ /** * @fileoverview Rule to enforce line breaks after each array element * @author Jan Peer Stöcklmair @@ -57793,7 +64377,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -57801,16 +64385,20 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce line breaks after each array element", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/array-element-newline" }, + fixable: "whitespace", + schema: [{ oneOf: [{ - enum: ["always", "never"] + enum: ["always", "never", "consistent"] }, { type: "object", properties: { @@ -57842,25 +64430,29 @@ module.exports = { /** * Normalizes a given option value. * - * @param {string|Object|undefined} option - An option value to parse. + * @param {string|Object|undefined} providedOption - An option value to parse. * @returns {{multiline: boolean, minItems: number}} Normalized option object. */ - function normalizeOptionValue(option) { + function normalizeOptionValue(providedOption) { + var consistent = false; var multiline = false; var minItems = void 0; - option = option || "always"; + var option = providedOption || "always"; - if (option === "always" || option.minItems === 0) { + if (!option || option === "always" || option.minItems === 0) { minItems = 0; } else if (option === "never") { minItems = Number.POSITIVE_INFINITY; + } else if (option === "consistent") { + consistent = true; + minItems = Number.POSITIVE_INFINITY; } else { multiline = Boolean(option.multiline); minItems = option.minItems || Number.POSITIVE_INFINITY; } - return { multiline: multiline, minItems: minItems }; + return { consistent: consistent, multiline: multiline, minItems: minItems }; } /** @@ -57947,7 +64539,6 @@ module.exports = { * Reports a given node if it violated this rule. * * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node. - * @param {{multiline: boolean, minItems: number}} options - An option object. * @returns {void} */ function check(node) { @@ -57977,7 +64568,23 @@ module.exports = { }); } - var needsLinebreaks = elements.length >= options.minItems || options.multiline && elementBreak; + var linebreaksCount = node.elements.map(function (element, i) { + var previousElement = elements[i - 1]; + + if (i === 0 || element === null || previousElement === null) { + return false; + } + + var commaToken = sourceCode.getFirstTokenBetween(previousElement, element, astUtils.isCommaToken); + var lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken); + var firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken); + + return !astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement); + }).filter(function (isBreak) { + return isBreak === true; + }).length; + + var needsLinebreaks = elements.length >= options.minItems || options.multiline && elementBreak || options.consistent && linebreaksCount > 0 && linebreaksCount < node.elements.length; elements.forEach(function (element, i) { var previousElement = elements[i - 1]; @@ -58013,7 +64620,7 @@ module.exports = { } }; -},{"../ast-utils":115}],135:[function(require,module,exports){ +},{"../util/ast-utils":405}],130:[function(require,module,exports){ /** * @fileoverview Rule to require braces in arrow function body. * @author Alberto Rodríguez @@ -58024,7 +64631,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -58032,6 +64639,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "require braces around arrow function bodies", category: "ECMAScript 6", @@ -58131,6 +64740,8 @@ module.exports = { messageId = "unexpectedEmptyBlock"; } else if (blockBody.length > 1) { messageId = "unexpectedOtherBlock"; + } else if (blockBody[0].argument === null) { + messageId = "unexpectedSingleBlock"; } else if (astUtils.isOpeningBraceToken(sourceCode.getFirstToken(blockBody[0], { skip: 1 }))) { messageId = "unexpectedObjectBlock"; } else { @@ -58219,7 +64830,7 @@ module.exports = { } }; -},{"../ast-utils":115}],136:[function(require,module,exports){ +},{"../util/ast-utils":405}],131:[function(require,module,exports){ /** * @fileoverview Rule to require parens in arrow function arguments. * @author Jxck @@ -58230,7 +64841,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -58238,6 +64849,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require parentheses around arrow function arguments", category: "ECMAScript 6", @@ -58361,7 +64974,7 @@ module.exports = { } }; -},{"../ast-utils":115}],137:[function(require,module,exports){ +},{"../util/ast-utils":405}],132:[function(require,module,exports){ /** * @fileoverview Rule to define spacing before/after arrow function's arrow. * @author Jxck @@ -58372,7 +64985,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -58380,6 +64993,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before and after the arrow in arrow functions", category: "ECMAScript 6", @@ -58519,7 +65134,7 @@ module.exports = { } }; -},{"../ast-utils":115}],138:[function(require,module,exports){ +},{"../util/ast-utils":405}],133:[function(require,module,exports){ /** * @fileoverview Rule to check for "block scoped" variables by binding context * @author Matt DuVall @@ -58532,6 +65147,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce the use of variables within the scope they are defined", category: "Best Practices", @@ -58638,7 +65255,7 @@ module.exports = { } }; -},{}],139:[function(require,module,exports){ +},{}],134:[function(require,module,exports){ /** * @fileoverview A rule to disallow or enforce spaces inside of single line blocks. * @author Toru Nagashima @@ -58646,7 +65263,7 @@ module.exports = { "use strict"; -var util = require("../ast-utils"); +var util = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -58654,6 +65271,8 @@ var util = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "disallow or enforce spaces inside of blocks after opening block and before closing block", category: "Stylistic Issues", @@ -58775,7 +65394,7 @@ module.exports = { } }; -},{"../ast-utils":115}],140:[function(require,module,exports){ +},{"../util/ast-utils":405}],135:[function(require,module,exports){ /** * @fileoverview Rule to flag block statements that do not use the one true brace style * @author Ian Christian Myers @@ -58783,7 +65402,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -58791,6 +65410,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent brace style for blocks", category: "Stylistic Issues", @@ -58969,7 +65590,7 @@ module.exports = { } }; -},{"../ast-utils":115}],141:[function(require,module,exports){ +},{"../util/ast-utils":405}],136:[function(require,module,exports){ /** * @fileoverview Enforce return after a callback. * @author Jamund Ferguson @@ -58982,6 +65603,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `return` statements after callbacks", category: "Node.js and CommonJS", @@ -59144,7 +65767,7 @@ module.exports = { } }; -},{}],142:[function(require,module,exports){ +},{}],137:[function(require,module,exports){ /** * @fileoverview Rule to flag non-camelcased identifiers * @author Nicholas C. Zakas @@ -59158,6 +65781,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce camelcase naming convention", category: "Stylistic Issues", @@ -59168,8 +65793,19 @@ module.exports = { schema: [{ type: "object", properties: { + ignoreDestructuring: { + type: "boolean" + }, properties: { enum: ["always", "never"] + }, + allow: { + type: "array", + items: [{ + type: "string" + }], + minItems: 0, + uniqueItems: true } }, additionalProperties: false @@ -59182,6 +65818,15 @@ module.exports = { create: function create(context) { + var options = context.options[0] || {}; + var properties = options.properties || ""; + var ignoreDestructuring = options.ignoreDestructuring || false; + var allow = options.allow || []; + + if (properties !== "always" && properties !== "never") { + properties = "always"; + } + //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- @@ -59202,6 +65847,44 @@ module.exports = { return name.indexOf("_") > -1 && name !== name.toUpperCase(); } + /** + * Checks if a string match the ignore list + * @param {string} name The string to check. + * @returns {boolean} if the string is ignored + * @private + */ + function isAllowed(name) { + return allow.findIndex(function (entry) { + return name === entry || name.match(new RegExp(entry)); + }) !== -1; + } + + /** + * Checks if a parent of a node is an ObjectPattern. + * @param {ASTNode} node The node to check. + * @returns {boolean} if the node is inside an ObjectPattern + * @private + */ + function isInsideObjectPattern(node) { + var current = node; + + while (current) { + var parent = current.parent; + + if (parent && parent.type === "Property" && parent.computed && parent.key === current) { + return false; + } + + if (current.type === "ObjectPattern") { + return true; + } + + current = parent; + } + + return false; + } + /** * Reports an AST node as a rule violation. * @param {ASTNode} node The node to report. @@ -59215,23 +65898,22 @@ module.exports = { } } - var options = context.options[0] || {}; - var properties = options.properties || ""; - - if (properties !== "always" && properties !== "never") { - properties = "always"; - } - return { Identifier: function Identifier(node) { /* * Leading and trailing underscores are commonly used to flag - * private/protected identifiers, strip them + * private/protected identifiers, strip them before checking if underscored */ - var name = node.name.replace(/^_+|_+$/g, ""), + var name = node.name, + nameIsUnderscored = isUnderscored(name.replace(/^_+|_+$/g, "")), effectiveParent = node.parent.type === "MemberExpression" ? node.parent.parent : node.parent; + // First, we ignore the node if it match the ignore list + if (isAllowed(name)) { + return; + } + // MemberExpressions get special rules if (node.parent.type === "MemberExpression") { @@ -59241,11 +65923,11 @@ module.exports = { } // Always report underscored object names - if (node.parent.object.type === "Identifier" && node.parent.object.name === node.name && isUnderscored(name)) { + if (node.parent.object.type === "Identifier" && node.parent.object.name === node.name && nameIsUnderscored) { report(node); // Report AssignmentExpressions only if they are the left side of the assignment - } else if (effectiveParent.type === "AssignmentExpression" && isUnderscored(name) && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name)) { + } else if (effectiveParent.type === "AssignmentExpression" && nameIsUnderscored && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name)) { report(node); } @@ -59257,9 +65939,13 @@ module.exports = { } else if (node.parent.type === "Property" || node.parent.type === "AssignmentPattern") { if (node.parent.parent && node.parent.parent.type === "ObjectPattern") { + if (node.parent.shorthand && node.parent.value.left && nameIsUnderscored) { + report(node); + } - if (node.parent.shorthand && node.parent.value.left && isUnderscored(name)) { + var assignmentKeyEqualsValue = node.parent.key.name === node.parent.value.name; + if (isUnderscored(name) && node.parent.computed) { report(node); } @@ -59268,18 +65954,21 @@ module.exports = { return; } - if (node.parent.value.name && isUnderscored(name)) { + var valueIsUnderscored = node.parent.value.name && nameIsUnderscored; + + // ignore destructuring if the option is set, unless a new identifier is created + if (valueIsUnderscored && !(assignmentKeyEqualsValue && ignoreDestructuring)) { report(node); } } - // "never" check properties - if (properties === "never") { + // "never" check properties or always ignore destructuring + if (properties === "never" || ignoreDestructuring && isInsideObjectPattern(node)) { return; } // don't check right hand side of AssignmentExpression to prevent duplicate warnings - if (isUnderscored(name) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && !(node.parent.right === node)) { + if (nameIsUnderscored && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && !(node.parent.right === node)) { report(node); } @@ -59287,12 +65976,12 @@ module.exports = { } else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].indexOf(node.parent.type) >= 0) { // Report only if the local imported identifier is underscored - if (node.parent.local && node.parent.local.name === node.name && isUnderscored(name)) { + if (node.parent.local && node.parent.local.name === node.name && nameIsUnderscored) { report(node); } // Report anything that is underscored that isn't a CallExpression - } else if (isUnderscored(name) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type)) { + } else if (nameIsUnderscored && !ALLOWED_PARENT_TYPES.has(effectiveParent.type)) { report(node); } } @@ -59300,7 +65989,7 @@ module.exports = { } }; -},{}],143:[function(require,module,exports){ +},{}],138:[function(require,module,exports){ /** * @fileoverview enforce or disallow capitalization of the first letter of a comment * @author Kevin Partington @@ -59312,7 +66001,7 @@ module.exports = { //------------------------------------------------------------------------------ var LETTER_PATTERN = require("../util/patterns/letters"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -59412,13 +66101,17 @@ function createRegExpForIgnorePatterns(normalizedOptions) { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce or disallow capitalization of the first letter of a comment", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/capitalized-comments" }, + fixable: "code", + schema: [{ enum: ["always", "never"] }, { oneOf: [SCHEMA_BODY, { type: "object", @@ -59592,7 +66285,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/patterns/letters":407}],144:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/patterns/letters":411}],139:[function(require,module,exports){ /** * @fileoverview Rule to enforce that all class methods use 'this'. * @author Patrick Williams @@ -59606,12 +66299,15 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce that class methods utilize `this`", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/class-methods-use-this" }, + schema: [{ type: "object", properties: { @@ -59709,7 +66405,7 @@ module.exports = { } }; -},{}],145:[function(require,module,exports){ +},{}],140:[function(require,module,exports){ /** * @fileoverview Rule to forbid or enforce dangling commas. * @author Ian Christian Myers @@ -59724,7 +66420,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -59786,13 +66482,17 @@ function normalizeOptions(optionValue) { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow trailing commas", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/comma-dangle" }, + fixable: "code", + schema: { definitions: { value: { @@ -60035,14 +66735,14 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],146:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],141:[function(require,module,exports){ /** * @fileoverview Comma spacing - validates spacing before and after comma * @author Vignesh Anand aka vegetableman. */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60050,6 +66750,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before and after commas", category: "Stylistic Issues", @@ -60218,7 +66920,7 @@ module.exports = { } }; -},{"../ast-utils":115}],147:[function(require,module,exports){ +},{"../util/ast-utils":405}],142:[function(require,module,exports){ /** * @fileoverview Comma style - enforces comma styles of two types: last and first * @author Vignesh Anand aka vegetableman @@ -60226,7 +66928,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60234,13 +66936,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent comma style", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/comma-style" }, + fixable: "code", + schema: [{ enum: ["first", "last"] }, { @@ -60255,6 +66961,7 @@ module.exports = { }, additionalProperties: false }], + messages: { unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.", expectedCommaFirst: "',' should be placed first.", @@ -60276,7 +66983,7 @@ module.exports = { NewExpression: true }; - if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) { + if (context.options.length === 2 && Object.prototype.hasOwnProperty.call(context.options[1], "exceptions")) { var keys = Object.keys(context.options[1].exceptions); for (var i = 0; i < keys.length; i++) { @@ -60298,7 +67005,7 @@ module.exports = { function getReplacedText(styleType, text) { switch (styleType) { case "between": - return "," + text.replace("\n", ""); + return "," + text.replace(astUtils.LINEBREAK_MATCHER, ""); case "first": return text + ","; @@ -60347,6 +67054,9 @@ module.exports = { } else if (!astUtils.isTokenOnSameLine(commaToken, currentItemToken) && !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { + var comment = sourceCode.getCommentsAfter(commaToken)[0]; + var styleType = comment && comment.type === "Block" && astUtils.isTokenOnSameLine(commaToken, comment) ? style : "between"; + // lone comma context.report({ node: reportItem, @@ -60355,7 +67065,7 @@ module.exports = { column: commaToken.loc.start.column }, messageId: "unexpectedLineBeforeAndAfterComma", - fix: getFixerFunction("between", previousItemToken, commaToken, currentItemToken) + fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) }); } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { @@ -60397,13 +67107,7 @@ module.exports = { items.forEach(function (item) { var commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken), - reportItem = item || currentItemToken, - tokenBeforeComma = sourceCode.getTokenBefore(commaToken); - - // Check if previous token is wrapped in parentheses - if (tokenBeforeComma && astUtils.isClosingParenToken(tokenBeforeComma)) { - previousItemToken = tokenBeforeComma; - } + reportItem = item || currentItemToken; /* * This works by comparing three token locations: @@ -60514,7 +67218,7 @@ module.exports = { } }; -},{"../ast-utils":115}],148:[function(require,module,exports){ +},{"../util/ast-utils":405}],143:[function(require,module,exports){ /** * @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity. * Counts the number of if, conditional, for, whilte, try, switch/case, @@ -60531,7 +67235,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60539,6 +67243,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum cyclomatic complexity allowed in a program", category: "Best Practices", @@ -60575,10 +67281,10 @@ module.exports = { var option = context.options[0]; var THRESHOLD = 20; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") { THRESHOLD = option.maximum; } - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { THRESHOLD = option.max; } if (typeof option === "number") { @@ -60671,14 +67377,14 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],149:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],144:[function(require,module,exports){ /** * @fileoverview Disallows or enforces spaces inside computed properties. * @author Jamund Ferguson */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60686,6 +67392,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing inside computed property brackets", category: "Stylistic Issues", @@ -60854,7 +67562,7 @@ module.exports = { } }; -},{"../ast-utils":115}],150:[function(require,module,exports){ +},{"../util/ast-utils":405}],145:[function(require,module,exports){ /** * @fileoverview Rule to flag consistent return values * @author Nicholas C. Zakas @@ -60867,7 +67575,7 @@ module.exports = { var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -60907,6 +67615,8 @@ function isClassConstructor(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `return` statements to either always or never specify values", category: "Best Practices", @@ -61041,7 +67751,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],151:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],146:[function(require,module,exports){ /** * @fileoverview Rule to enforce consistent naming of "this" context variables * @author Raphael Pigulla @@ -61054,6 +67764,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce consistent naming when capturing the current execution context", category: "Stylistic Issues", @@ -61188,7 +67900,7 @@ module.exports = { } }; -},{}],152:[function(require,module,exports){ +},{}],147:[function(require,module,exports){ /** * @fileoverview A rule to verify `super()` callings in constructor. * @author Toru Nagashima @@ -61275,6 +67987,8 @@ function isPossibleConstructor(node) { module.exports = { meta: { + type: "problem", + docs: { description: "require `super()` calls in constructors", category: "ECMAScript 6", @@ -61576,7 +68290,7 @@ module.exports = { } }; -},{}],153:[function(require,module,exports){ +},{}],148:[function(require,module,exports){ /** * @fileoverview Rule to flag statements without curly braces * @author Nicholas C. Zakas @@ -61587,7 +68301,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -61595,6 +68309,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce consistent brace style for all control statements", category: "Best Practices", @@ -61708,12 +68424,10 @@ module.exports = { return true; } - node = node.consequent.body[0]; - while (node) { - if (node.type === "IfStatement" && !node.alternate) { + for (var currentNode = node.consequent.body[0]; currentNode; currentNode = astUtils.getTrailingStatement(currentNode)) { + if (currentNode.type === "IfStatement" && !currentNode.alternate) { return true; } - node = astUtils.getTrailingStatement(node); } } @@ -61880,14 +68594,13 @@ module.exports = { function prepareIfChecks(node) { var preparedChecks = []; - do { - preparedChecks.push(prepareCheck(node, node.consequent, "if", { condition: true })); - if (node.alternate && node.alternate.type !== "IfStatement") { - preparedChecks.push(prepareCheck(node, node.alternate, "else")); + for (var currentNode = node; currentNode; currentNode = currentNode.alternate) { + preparedChecks.push(prepareCheck(currentNode, currentNode.consequent, "if", { condition: true })); + if (currentNode.alternate && currentNode.alternate.type !== "IfStatement") { + preparedChecks.push(prepareCheck(currentNode, currentNode.alternate, "else")); break; } - node = node.alternate; - } while (node); + } if (consistent) { @@ -61942,7 +68655,7 @@ module.exports = { } }; -},{"../ast-utils":115}],154:[function(require,module,exports){ +},{"../util/ast-utils":405}],149:[function(require,module,exports){ /** * @fileoverview require default case in switch statements * @author Aliaksei Shytkin @@ -61957,6 +68670,8 @@ var DEFAULT_COMMENT_PATTERN = /^no default$/i; module.exports = { meta: { + type: "suggestion", + docs: { description: "require `default` cases in `switch` statements", category: "Best Practices", @@ -62038,7 +68753,7 @@ module.exports = { } }; -},{}],155:[function(require,module,exports){ +},{}],150:[function(require,module,exports){ /** * @fileoverview Validates newlines before and after dots * @author Greg Cochard @@ -62046,7 +68761,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -62054,6 +68769,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent newlines before and after dots", category: "Best Practices", @@ -62136,7 +68853,7 @@ module.exports = { } }; -},{"../ast-utils":115}],156:[function(require,module,exports){ +},{"../util/ast-utils":405}],151:[function(require,module,exports){ /** * @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible. * @author Josh Perez @@ -62147,7 +68864,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -62158,6 +68875,8 @@ var keywords = require("../util/keywords"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce dot notation whenever possible", category: "Best Practices", @@ -62278,7 +68997,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/keywords":405}],157:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/keywords":409}],152:[function(require,module,exports){ /** * @fileoverview Require or disallow newline at the end of files * @author Nodeca Team @@ -62297,16 +69016,21 @@ var lodash = require("lodash"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow newline at the end of files", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/eol-last" }, + fixable: "whitespace", + schema: [{ enum: ["always", "never", "unix", "windows"] }], + messages: { missing: "Newline required at end of file but not found.", unexpected: "Newline not allowed at end of file." @@ -62385,7 +69109,7 @@ module.exports = { } }; -},{"lodash":89}],158:[function(require,module,exports){ +},{"lodash":92}],153:[function(require,module,exports){ /** * @fileoverview Rule to flag statements that use != and == instead of !== and === * @author Nicholas C. Zakas @@ -62399,7 +69123,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -62407,6 +69131,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "require the use of `===` and `!==`", category: "Best Practices", @@ -62496,7 +69222,6 @@ module.exports = { /** * Gets the location (line and column) of the binary expression's operator * @param {ASTNode} node The binary expression node to check - * @param {string} operator The operator to find * @returns {Object} { line, column } location of operator * @private */ @@ -62559,7 +69284,7 @@ module.exports = { } }; -},{"../ast-utils":115}],159:[function(require,module,exports){ +},{"../util/ast-utils":405}],154:[function(require,module,exports){ /** * @fileoverview enforce "for" loop update clause moving the counter in the right direction.(for-direction) * @author Aladdin-ADD @@ -62573,14 +69298,21 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "enforce \"for\" loop update clause moving the counter in the right direction.", category: "Possible Errors", - recommended: false, + recommended: true, url: "https://eslint.org/docs/rules/for-direction" }, + fixable: null, - schema: [] + schema: [], + + messages: { + incorrectDirection: "The update clause in this loop moves the variable in the wrong direction." + } }, create: function create(context) { @@ -62593,7 +69325,7 @@ module.exports = { function report(node) { context.report({ node: node, - message: "The update clause in this loop moves the variable in the wrong direction." + messageId: "incorrectDirection" }); } @@ -62667,7 +69399,7 @@ module.exports = { } }; -},{}],160:[function(require,module,exports){ +},{}],155:[function(require,module,exports){ /** * @fileoverview Rule to control spacing within function calls * @author Matt DuVall @@ -62679,7 +69411,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -62687,6 +69419,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow spacing between function identifiers and their invocations", category: "Stylistic Issues", @@ -62695,6 +69429,7 @@ module.exports = { }, fixable: "whitespace", + schema: { anyOf: [{ type: "array", @@ -62719,6 +69454,11 @@ module.exports = { minItems: 0, maxItems: 2 }] + }, + + messages: { + unexpected: "Unexpected newline between function name and paren.", + missing: "Missing space between function name and paren." } }, @@ -62778,7 +69518,7 @@ module.exports = { context.report({ node: node, loc: lastCalleeToken.loc.start, - message: "Unexpected space between function name and paren.", + messageId: "unexpected", fix: function fix(fixer) { /* @@ -62796,7 +69536,7 @@ module.exports = { context.report({ node: node, loc: lastCalleeToken.loc.start, - message: "Missing space between function name and paren.", + messageId: "missing", fix: function fix(fixer) { return fixer.insertTextBefore(parenToken, " "); } @@ -62805,7 +69545,7 @@ module.exports = { context.report({ node: node, loc: lastCalleeToken.loc.start, - message: "Unexpected newline between function name and paren.", + messageId: "unexpected", fix: function fix(fixer) { return fixer.replaceTextRange([prevToken.range[1], parenToken.range[0]], " "); } @@ -62820,7 +69560,7 @@ module.exports = { } }; -},{"../ast-utils":115}],161:[function(require,module,exports){ +},{"../util/ast-utils":405}],156:[function(require,module,exports){ /** * @fileoverview Rule to require function names to match the name of the variable or property to which they are assigned. * @author Annie Zhang, Pavel Strashkin @@ -62834,7 +69574,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var esutils = require("esutils"); //-------------------------------------------------------------------------- @@ -62883,6 +69623,9 @@ var alwaysOrNever = { enum: ["always", "never"] }; var optionsObject = { type: "object", properties: { + considerPropertyDescriptor: { + type: "boolean" + }, includeCommonJSModuleExports: { type: "boolean" } @@ -62892,6 +69635,8 @@ var optionsObject = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require function names to match the name of the variable or property to which they are assigned", category: "Stylistic Issues", @@ -62909,15 +69654,37 @@ module.exports = { additionalItems: false, items: [optionsObject] }] + }, + + messages: { + matchProperty: "Function name `{{funcName}}` should match property name `{{name}}`", + matchVariable: "Function name `{{funcName}}` should match variable name `{{name}}`", + notMatchProperty: "Function name `{{funcName}}` should not match property name `{{name}}`", + notMatchVariable: "Function name `{{funcName}}` should not match variable name `{{name}}`" } }, create: function create(context) { var options = (_typeof(context.options[0]) === "object" ? context.options[0] : context.options[1]) || {}; var nameMatches = typeof context.options[0] === "string" ? context.options[0] : "always"; + var considerPropertyDescriptor = options.considerPropertyDescriptor; var includeModuleExports = options.includeCommonJSModuleExports; var ecmaVersion = context.parserOptions && context.parserOptions.ecmaVersion ? context.parserOptions.ecmaVersion : 5; + /** + * Check whether node is a certain CallExpression. + * @param {string} objName object name + * @param {string} funcName function name + * @param {ASTNode} node The node to check + * @returns {boolean} `true` if node matches CallExpression + */ + function isPropertyCall(objName, funcName, node) { + if (!node) { + return false; + } + return node.type === "CallExpression" && node.callee.object.name === objName && node.callee.property.name === funcName; + } + /** * Compares identifiers based on the nameMatches option * @param {string} x the first identifier @@ -62937,20 +69704,20 @@ module.exports = { * @returns {void} */ function report(node, name, funcName, isProp) { - var message = void 0; + var messageId = void 0; if (nameMatches === "always" && isProp) { - message = "Function name `{{funcName}}` should match property name `{{name}}`"; + messageId = "matchProperty"; } else if (nameMatches === "always") { - message = "Function name `{{funcName}}` should match variable name `{{name}}`"; + messageId = "matchVariable"; } else if (isProp) { - message = "Function name `{{funcName}}` should not match property name `{{name}}`"; + messageId = "notMatchProperty"; } else { - message = "Function name `{{funcName}}` should not match variable name `{{name}}`"; + messageId = "notMatchVariable"; } context.report({ node: node, - message: message, + messageId: messageId, data: { name: name, funcName: funcName @@ -62996,9 +69763,38 @@ module.exports = { if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && !isStringLiteral(node.key)) { return; } - if (node.key.type === "Identifier" && shouldWarn(node.key.name, node.value.id.name)) { - report(node, node.key.name, node.value.id.name, true); - } else if (isStringLiteral(node.key) && isIdentifier(node.key.value, ecmaVersion) && shouldWarn(node.key.value, node.value.id.name)) { + + if (node.key.type === "Identifier") { + var functionName = node.value.id.name; + var propertyName = node.key.name; + + if (considerPropertyDescriptor && propertyName === "value") { + if (isPropertyCall("Object", "defineProperty", node.parent.parent) || isPropertyCall("Reflect", "defineProperty", node.parent.parent)) { + var property = node.parent.parent.arguments[1]; + + if (isStringLiteral(property) && shouldWarn(property.value, functionName)) { + report(node, property.value, functionName, true); + } + } else if (isPropertyCall("Object", "defineProperties", node.parent.parent.parent.parent)) { + propertyName = node.parent.parent.key.name; + if (!node.parent.parent.computed && shouldWarn(propertyName, functionName)) { + report(node, propertyName, functionName, true); + } + } else if (isPropertyCall("Object", "create", node.parent.parent.parent.parent)) { + propertyName = node.parent.parent.key.name; + if (!node.parent.parent.computed && shouldWarn(propertyName, functionName)) { + report(node, propertyName, functionName, true); + } + } else if (shouldWarn(propertyName, functionName)) { + report(node, propertyName, functionName, true); + } + } else if (shouldWarn(propertyName, functionName)) { + report(node, propertyName, functionName, true); + } + return; + } + + if (isStringLiteral(node.key) && isIdentifier(node.key.value, ecmaVersion) && shouldWarn(node.key.value, node.value.id.name)) { report(node, node.key.value, node.value.id.name, true); } } @@ -63006,7 +69802,7 @@ module.exports = { } }; -},{"../ast-utils":115,"esutils":78}],162:[function(require,module,exports){ +},{"../util/ast-utils":405,"esutils":80}],157:[function(require,module,exports){ /** * @fileoverview Rule to warn when a function expression does not have a name. * @author Kyle T. Nunery @@ -63018,7 +69814,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); /** * Checks whether or not a given variable is a function name. @@ -63035,6 +69831,8 @@ function isFunctionName(variable) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow named `function` expressions", category: "Stylistic Issues", @@ -63042,14 +69840,45 @@ module.exports = { url: "https://eslint.org/docs/rules/func-names" }, - schema: [{ - enum: ["always", "as-needed", "never"] - }] + schema: { + definitions: { + value: { + enum: ["always", "as-needed", "never"] + } + }, + items: [{ + $ref: "#/definitions/value" + }, { + type: "object", + properties: { + generators: { + $ref: "#/definitions/value" + } + }, + additionalProperties: false + }] + }, + + messages: { + unnamed: "Unexpected unnamed {{name}}.", + named: "Unexpected named {{name}}." + } }, create: function create(context) { - var never = context.options[0] === "never"; - var asNeeded = context.options[0] === "as-needed"; + + /** + * Returns the config option for the given node. + * @param {ASTNode} node - A node to get the config for. + * @returns {string} The config option. + */ + function getConfigForNode(node) { + if (node.generator && context.options.length > 1 && context.options[1].generators) { + return context.options[1].generators; + } + + return context.options[0] || "always"; + } /** * Determines whether the current FunctionExpression node is a get, set, or @@ -63075,6 +69904,32 @@ module.exports = { return isObjectOrClassMethod(node) || parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node || parent.type === "Property" && parent.value === node || parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node || parent.type === "ExportDefaultDeclaration" && parent.declaration === node || parent.type === "AssignmentPattern" && parent.right === node; } + /** + * Reports that an unnamed function should be named + * @param {ASTNode} node - The node to report in the event of an error. + * @returns {void} + */ + function reportUnexpectedUnnamedFunction(node) { + context.report({ + node: node, + messageId: "unnamed", + data: { name: astUtils.getFunctionNameWithKind(node) } + }); + } + + /** + * Reports that a named function should be unnamed + * @param {ASTNode} node - The node to report in the event of an error. + * @returns {void} + */ + function reportUnexpectedNamedFunction(node) { + context.report({ + node: node, + messageId: "named", + data: { name: astUtils.getFunctionNameWithKind(node) } + }); + } + return { "FunctionExpression:exit": function FunctionExpressionExit(node) { @@ -63086,23 +69941,19 @@ module.exports = { } var hasName = Boolean(node.id && node.id.name); - var name = astUtils.getFunctionNameWithKind(node); + var config = getConfigForNode(node); - if (never) { + if (config === "never") { if (hasName) { - context.report({ - node: node, - message: "Unexpected named {{name}}.", - data: { name: name } - }); + reportUnexpectedNamedFunction(node); + } + } else if (config === "as-needed") { + if (!hasName && !hasInferredName(node)) { + reportUnexpectedUnnamedFunction(node); } } else { - if (!hasName && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) { - context.report({ - node: node, - message: "Unexpected unnamed {{name}}.", - data: { name: name } - }); + if (!hasName && !isObjectOrClassMethod(node)) { + reportUnexpectedUnnamedFunction(node); } } } @@ -63110,7 +69961,7 @@ module.exports = { } }; -},{"../ast-utils":115}],163:[function(require,module,exports){ +},{"../util/ast-utils":405}],158:[function(require,module,exports){ /** * @fileoverview Rule to enforce a particular function style * @author Nicholas C. Zakas @@ -63123,6 +69974,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce the consistent use of either `function` declarations or expressions", category: "Stylistic Issues", @@ -63140,7 +69993,12 @@ module.exports = { } }, additionalProperties: false - }] + }], + + messages: { + expression: "Expected a function expression.", + declaration: "Expected a function declaration." + } }, create: function create(context) { @@ -63155,7 +70013,7 @@ module.exports = { stack.push(false); if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { - context.report({ node: node, message: "Expected a function expression." }); + context.report({ node: node, messageId: "expression" }); } }, "FunctionDeclaration:exit": function FunctionDeclarationExit() { @@ -63165,7 +70023,7 @@ module.exports = { stack.push(false); if (enforceDeclarations && node.parent.type === "VariableDeclarator") { - context.report({ node: node.parent, message: "Expected a function declaration." }); + context.report({ node: node.parent, messageId: "declaration" }); } }, "FunctionExpression:exit": function FunctionExpressionExit() { @@ -63187,7 +70045,7 @@ module.exports = { var hasThisExpr = stack.pop(); if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { - context.report({ node: node.parent, message: "Expected a function declaration." }); + context.report({ node: node.parent, messageId: "declaration" }); } }; } @@ -63196,7 +70054,7 @@ module.exports = { } }; -},{}],164:[function(require,module,exports){ +},{}],159:[function(require,module,exports){ /** * @fileoverview enforce consistent line breaks inside function parentheses * @author Teddy Katz @@ -63209,7 +70067,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -63217,13 +70075,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent line breaks inside function parentheses", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/function-paren-newline" }, + fixable: "whitespace", + schema: [{ oneOf: [{ enum: ["always", "never", "consistent", "multiline"] @@ -63237,7 +70099,14 @@ module.exports = { }, additionalProperties: false }] - }] + }], + + messages: { + expectedBefore: "Expected newline before ')'.", + expectedAfter: "Expected newline after '('.", + unexpectedBefore: "Unexpected newline before '('.", + unexpectedAfter: "Unexpected newline after ')'." + } }, create: function create(context) { @@ -63297,7 +70166,7 @@ module.exports = { if (hasLeftNewline && !needsNewlines) { context.report({ node: leftParen, - message: "Unexpected newline after '('.", + messageId: "unexpectedAfter", fix: function fix(fixer) { return sourceCode.getText().slice(leftParen.range[1], tokenAfterLeftParen.range[0]).trim() @@ -63308,7 +70177,7 @@ module.exports = { } else if (!hasLeftNewline && needsNewlines) { context.report({ node: leftParen, - message: "Expected a newline after '('.", + messageId: "expectedAfter", fix: function fix(fixer) { return fixer.insertTextAfter(leftParen, "\n"); } @@ -63318,7 +70187,7 @@ module.exports = { if (hasRightNewline && !needsNewlines) { context.report({ node: rightParen, - message: "Unexpected newline before ')'.", + messageId: "unexpectedBefore", fix: function fix(fixer) { return sourceCode.getText().slice(tokenBeforeRightParen.range[1], rightParen.range[0]).trim() @@ -63329,7 +70198,7 @@ module.exports = { } else if (!hasRightNewline && needsNewlines) { context.report({ node: rightParen, - message: "Expected a newline before ')'.", + messageId: "expectedBefore", fix: function fix(fixer) { return fixer.insertTextBefore(rightParen, "\n"); } @@ -63418,7 +70287,7 @@ module.exports = { } }; -},{"../ast-utils":115}],165:[function(require,module,exports){ +},{"../util/ast-utils":405}],160:[function(require,module,exports){ /** * @fileoverview Rule to check the spacing around the * in generator functions. * @author Jamund Ferguson @@ -63445,6 +70314,8 @@ var OVERRIDE_SCHEMA = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing around `*` operators in generator functions", category: "ECMAScript 6", @@ -63468,7 +70339,14 @@ module.exports = { }, additionalProperties: false }] - }] + }], + + messages: { + missingBefore: "Missing space before *.", + missingAfter: "Missing space after *.", + unexpectedBefore: "Unexpected space before *.", + unexpectedAfter: "Unexpected space after *." + } }, create: function create(context) { @@ -63496,7 +70374,6 @@ module.exports = { } var modes = function (option) { - option = option || {}; var defaults = optionToDefinition(option, optionDefinitions.before); return { @@ -63504,7 +70381,7 @@ module.exports = { anonymous: optionToDefinition(option.anonymous, defaults), method: optionToDefinition(option.method, defaults) }; - }(context.options[0]); + }(context.options[0] || {}); var sourceCode = context.getSourceCode(); @@ -63528,6 +70405,15 @@ module.exports = { return sourceCode.getFirstToken(node.parent.method || node.parent.type === "MethodDefinition" ? node.parent : node, isStarToken); } + /** + * capitalize a given string. + * @param {string} str the given string. + * @returns {string} the capitalized string. + */ + function capitalize(str) { + return str[0].toUpperCase() + str.slice(1); + } + /** * Checks the spacing between two tokens before or after the star token. * @@ -63544,17 +70430,11 @@ module.exports = { var after = leftToken.value === "*"; var spaceRequired = modes[kind][side]; var node = after ? leftToken : rightToken; - var type = spaceRequired ? "Missing" : "Unexpected"; - var message = "{{type}} space {{side}} *."; - var data = { - type: type, - side: side - }; + var messageId = "" + (spaceRequired ? "missing" : "unexpected") + capitalize(side); context.report({ node: node, - message: message, - data: data, + messageId: messageId, fix: function fix(fixer) { if (spaceRequired) { if (after) { @@ -63606,7 +70486,7 @@ module.exports = { } }; -},{}],166:[function(require,module,exports){ +},{}],161:[function(require,module,exports){ /** * @fileoverview Enforces that a return statement is present in property getters. * @author Aladdin-ADD(hh_2013@foxmail.com) @@ -63618,7 +70498,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -63653,13 +70533,17 @@ function getId(node) { module.exports = { meta: { + type: "problem", + docs: { description: "enforce `return` statements in getters", category: "Possible Errors", - recommended: false, + recommended: true, url: "https://eslint.org/docs/rules/getter-return" }, + fixable: null, + schema: [{ type: "object", properties: { @@ -63668,7 +70552,12 @@ module.exports = { } }, additionalProperties: false - }] + }], + + messages: { + expected: "Expected to return a value in {{name}}.", + expectedAlways: "Expected {{name}} to always return a value." + } }, create: function create(context) { @@ -63698,7 +70587,7 @@ module.exports = { context.report({ node: node, loc: getId(node).loc.start, - message: funcInfo.hasReturn ? "Expected {{name}} to always return a value." : "Expected to return a value in {{name}}.", + messageId: funcInfo.hasReturn ? "expectedAlways" : "expected", data: { name: astUtils.getFunctionNameWithKind(funcInfo.node) } @@ -63762,7 +70651,7 @@ module.exports = { if (!options.allowImplicit && !node.argument) { context.report({ node: node, - message: "Expected to return a value in {{name}}.", + messageId: "expected", data: { name: astUtils.getFunctionNameWithKind(funcInfo.node) } @@ -63779,7 +70668,7 @@ module.exports = { } }; -},{"../ast-utils":115}],167:[function(require,module,exports){ +},{"../util/ast-utils":405}],162:[function(require,module,exports){ /** * @fileoverview Rule for disallowing require() outside of the top-level module context * @author Jamund Ferguson @@ -63821,6 +70710,8 @@ function isShadowed(scope, node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `require()` calls to be placed at top-level module scope", category: "Node.js and CommonJS", @@ -63850,7 +70741,7 @@ module.exports = { } }; -},{}],168:[function(require,module,exports){ +},{}],163:[function(require,module,exports){ /** * @fileoverview Rule to flag for-in loops without if statements inside * @author Nicholas C. Zakas @@ -63864,6 +70755,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `for-in` loops to include an `if` statement", category: "Best Practices", @@ -63921,7 +70814,7 @@ module.exports = { } }; -},{}],169:[function(require,module,exports){ +},{}],164:[function(require,module,exports){ /** * @fileoverview Ensure handling of errors when we know they exist. * @author Jamund Ferguson @@ -63935,6 +70828,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require error handling in callbacks", category: "Node.js and CommonJS", @@ -63979,7 +70874,7 @@ module.exports = { /** * Get the parameters of a given function scope. * @param {Object} scope The function scope. - * @returns {array} All parameters of the given scope. + * @returns {Array} All parameters of the given scope. */ function getParameters(scope) { return scope.variables.filter(function (variable) { @@ -64012,7 +70907,7 @@ module.exports = { } }; -},{}],170:[function(require,module,exports){ +},{}],165:[function(require,module,exports){ /** * @fileoverview Rule that warns when identifier names that are * blacklisted in the configuration are used. @@ -64027,6 +70922,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified identifiers", category: "Stylistic Issues", @@ -64125,7 +71022,7 @@ module.exports = { } }; -},{}],171:[function(require,module,exports){ +},{}],166:[function(require,module,exports){ /** * @fileoverview Rule that warns when identifier names are shorter or longer * than the values provided in configuration. @@ -64140,6 +71037,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce minimum and maximum identifier lengths", category: "Stylistic Issues", @@ -64238,7 +71137,7 @@ module.exports = { } }; -},{}],172:[function(require,module,exports){ +},{}],167:[function(require,module,exports){ /** * @fileoverview Rule to flag non-matching identifiers * @author Matthieu Larcher @@ -64252,6 +71151,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require identifiers to match a specified regular expression", category: "Stylistic Issues", @@ -64266,6 +71167,12 @@ module.exports = { properties: { properties: { type: "boolean" + }, + onlyDeclarations: { + type: "boolean" + }, + ignoreDestructuring: { + type: "boolean" } } }] @@ -64274,15 +71181,25 @@ module.exports = { create: function create(context) { //-------------------------------------------------------------------------- - // Helpers + // Options //-------------------------------------------------------------------------- - var pattern = context.options[0] || "^.+$", regexp = new RegExp(pattern); var options = context.options[1] || {}, properties = !!options.properties, - onlyDeclarations = !!options.onlyDeclarations; + onlyDeclarations = !!options.onlyDeclarations, + ignoreDestructuring = !!options.ignoreDestructuring; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + // contains reported nodes to avoid reporting twice on destructuring with shorthand notation + var reported = new Map(); + var ALLOWED_PARENT_TYPES = new Set(["CallExpression", "NewExpression"]); + var DECLARATION_TYPES = new Set(["FunctionDeclaration", "VariableDeclarator"]); + var IMPORT_TYPES = new Set(["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"]); /** * Checks if a string matches the provided pattern @@ -64294,6 +71211,27 @@ module.exports = { return !regexp.test(name); } + /** + * Checks if a parent of a node is an ObjectPattern. + * @param {ASTNode} node The node to check. + * @returns {boolean} if the node is inside an ObjectPattern + * @private + */ + function isInsideObjectPattern(node) { + var parent = node.parent; + + + while (parent) { + if (parent.type === "ObjectPattern") { + return true; + } + + parent = parent.parent; + } + + return false; + } + /** * Verifies if we should report an error or not based on the effective * parent node and the identifier name. @@ -64302,7 +71240,7 @@ module.exports = { * @returns {boolean} whether an error should be reported or not */ function shouldReport(effectiveParent, name) { - return effectiveParent.type !== "CallExpression" && effectiveParent.type !== "NewExpression" && isInvalid(name); + return (!onlyDeclarations || DECLARATION_TYPES.has(effectiveParent.type)) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && isInvalid(name); } /** @@ -64312,14 +71250,17 @@ module.exports = { * @private */ function report(node) { - context.report({ - node: node, - message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", - data: { - name: node.name, - pattern: pattern - } - }); + if (!reported.has(node)) { + context.report({ + node: node, + message: "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", + data: { + name: node.name, + pattern: pattern + } + }); + reported.set(node, true); + } } return { @@ -64340,57 +71281,104 @@ module.exports = { report(node); } + // Report AssignmentExpressions left side's assigned variable id + } else if (effectiveParent.type === "AssignmentExpression" && effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name) { + if (isInvalid(name)) { + report(node); + } + // Report AssignmentExpressions only if they are the left side of the assignment - } else if (effectiveParent.type === "AssignmentExpression" && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === name)) { + } else if (effectiveParent.type === "AssignmentExpression" && effectiveParent.right.type !== "MemberExpression") { if (isInvalid(name)) { report(node); } } - } else if (parent.type === "Property") { - if (!properties || parent.key.name !== name) { + /* + * Properties have their own rules, and + * AssignmentPattern nodes can be treated like Properties: + * e.g.: const { no_camelcased = false } = bar; + */ + } else if (parent.type === "Property" || parent.type === "AssignmentPattern") { + + if (parent.parent && parent.parent.type === "ObjectPattern") { + if (parent.shorthand && parent.value.left && isInvalid(name)) { + + report(node); + } + + var assignmentKeyEqualsValue = parent.key.name === parent.value.name; + + // prevent checking righthand side of destructured object + if (!assignmentKeyEqualsValue && parent.key === node) { + return; + } + + var valueIsInvalid = parent.value.name && isInvalid(name); + + // ignore destructuring if the option is set, unless a new identifier is created + if (valueIsInvalid && !(assignmentKeyEqualsValue && ignoreDestructuring)) { + report(node); + } + } + + // never check properties or always ignore destructuring + if (!properties || ignoreDestructuring && isInsideObjectPattern(node)) { return; } - if (shouldReport(effectiveParent, name)) { + // don't check right hand side of AssignmentExpression to prevent duplicate warnings + if (parent.right !== node && shouldReport(effectiveParent, name)) { report(node); } - } else { - var isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; - if (onlyDeclarations && !isDeclaration) { - return; - } + // Check if it's an import specifier + } else if (IMPORT_TYPES.has(parent.type)) { - if (shouldReport(effectiveParent, name)) { + // Report only if the local imported identifier is invalid + if (parent.local && parent.local.name === node.name && isInvalid(name)) { report(node); } + + // Report anything that is invalid that isn't a CallExpression + } else if (shouldReport(effectiveParent, name)) { + report(node); } } }; } }; -},{}],173:[function(require,module,exports){ +},{}],168:[function(require,module,exports){ /** * @fileoverview enforce the location of arrow function bodies * @author Sharmila Jesupaul */ "use strict"; +var _require = require("../util/ast-utils"), + isArrowToken = _require.isArrowToken, + isParenthesised = _require.isParenthesised, + isOpeningParenToken = _require.isOpeningParenToken; + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ + module.exports = { meta: { + type: "layout", + docs: { description: "enforce the location of arrow function bodies", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/implicit-arrow-linebreak" }, + fixable: "whitespace", + schema: [{ enum: ["beside", "below"] }] @@ -64410,10 +71398,134 @@ module.exports = { return context.options[0] || "beside"; } + /** + * Formats the comments depending on whether it's a line or block comment. + * @param {Comment[]} comments The array of comments between the arrow and body + * @param {Integer} column The column number of the first token + * @returns {string} A string of comment text joined by line breaks + */ + function formatComments(comments, column) { + var whiteSpaces = " ".repeat(column); + + return comments.map(function (comment) { + + if (comment.type === "Line") { + return "//" + comment.value; + } + + return "/*" + comment.value + "*/"; + }).join("\n" + whiteSpaces) + "\n" + whiteSpaces; + } + + /** + * Finds the first token to prepend comments to depending on the parent type + * @param {Node} node The validated node + * @returns {Token|Node} The node to prepend comments to + */ + function findFirstToken(node) { + switch (node.parent.type) { + case "VariableDeclarator": + + // If the parent is first or only declarator, return the declaration, else, declarator + return sourceCode.getFirstToken(node.parent.parent.declarations.length === 1 || node.parent.parent.declarations[0].id.name === node.parent.id.name ? node.parent.parent : node.parent); + case "CallExpression": + case "Property": + + // find the object key + return sourceCode.getFirstToken(node.parent); + default: + return node; + } + } + + /** + * Helper function for adding parentheses fixes for nodes containing nested arrow functions + * @param {Fixer} fixer Fixer + * @param {Token} arrow - The arrow token + * @param {ASTNode} arrowBody - The arrow function body + * @returns {Function[]} autofixer -- wraps function bodies with parentheses + */ + function addParentheses(fixer, arrow, arrowBody) { + var parenthesesFixes = []; + var closingParentheses = ""; + + var followingBody = arrowBody; + var currentArrow = arrow; + + while (currentArrow) { + if (!isParenthesised(sourceCode, followingBody)) { + parenthesesFixes.push(fixer.insertTextAfter(currentArrow, " (")); + + var paramsToken = sourceCode.getTokenBefore(currentArrow, function (token) { + return isOpeningParenToken(token) || token.type === "Identifier"; + }); + + var whiteSpaces = " ".repeat(paramsToken.loc.start.column); + + closingParentheses = "\n" + whiteSpaces + ")" + closingParentheses; + } + + currentArrow = sourceCode.getTokenAfter(currentArrow, isArrowToken); + + if (currentArrow) { + followingBody = sourceCode.getTokenAfter(currentArrow, function (token) { + return !isOpeningParenToken(token); + }); + } + } + + return [].concat(parenthesesFixes, [fixer.insertTextAfter(arrowBody, closingParentheses)]); + } + + /** + * Autofixes the function body to collapse onto the same line as the arrow. + * If comments exist, prepends the comments before the arrow function. + * If the function body contains arrow functions, appends the function bodies with parentheses. + * @param {Token} arrowToken The arrow token. + * @param {ASTNode} arrowBody the function body + * @param {ASTNode} node The evaluated node + * @returns {Function} autofixer -- validates the node to adhere to besides + */ + function autoFixBesides(arrowToken, arrowBody, node) { + return function (fixer) { + var placeBesides = fixer.replaceTextRange([arrowToken.range[1], arrowBody.range[0]], " "); + + var comments = sourceCode.getCommentsInside(node).filter(function (comment) { + return comment.loc.start.line < arrowBody.loc.start.line; + }); + + if (comments.length) { + + // If the grandparent is not a variable declarator + if (arrowBody.parent && arrowBody.parent.parent && arrowBody.parent.parent.type !== "VariableDeclarator") { + + // If any arrow functions follow, return the necessary parens fixes. + if (sourceCode.getTokenAfter(arrowToken, isArrowToken) && arrowBody.parent.parent.type !== "VariableDeclarator") { + return addParentheses(fixer, arrowToken, arrowBody); + } + + // If any arrow functions precede, the necessary fixes have already been returned, so return null. + if (sourceCode.getTokenBefore(arrowToken, isArrowToken) && arrowBody.parent.parent.type !== "VariableDeclarator") { + return null; + } + } + + var firstToken = findFirstToken(node); + + var commentText = formatComments(comments, firstToken.loc.start.column); + + var commentBeforeExpression = fixer.insertTextBeforeRange(firstToken.range, commentText); + + return [placeBesides, commentBeforeExpression]; + } + + return placeBesides; + }; + } + /** * Validates the location of an arrow function body * @param {ASTNode} node The arrow function body - * @param {string} keywordName The applicable keyword name for the arrow function body * @returns {void} */ function validateExpression(node) { @@ -64449,9 +71561,7 @@ module.exports = { context.report({ node: fixerTarget, message: "Expected no linebreak before this expression.", - fix: function fix(fixer) { - return fixer.replaceTextRange([tokenBefore.range[1], fixerTarget.range[0]], " "); - } + fix: autoFixBesides(tokenBefore, fixerTarget, node) }); } } @@ -64467,7 +71577,7 @@ module.exports = { } }; -},{}],174:[function(require,module,exports){ +},{"../util/ast-utils":405}],169:[function(require,module,exports){ /** * @fileoverview This option sets a specific tab width for your code * @@ -64484,7 +71594,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -64493,16 +71603,19 @@ var astUtils = require("../ast-utils"); /* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */ module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent indentation", category: "Stylistic Issues", recommended: false, - replacedBy: ["indent"], url: "https://eslint.org/docs/rules/indent-legacy" }, deprecated: true, + replacedBy: ["indent"], + fixable: "whitespace", schema: [{ @@ -64745,7 +71858,6 @@ module.exports = { * @param {int} gottenTabs Indentation tab count in the actual node/code * @param {Object=} loc Error line and column location * @param {boolean} isLastNodeCheck Is the error for last node check - * @param {int} lastNodeCheckEndOffset Number of charecters to skip from the end * @returns {void} */ function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck) { @@ -64816,7 +71928,6 @@ module.exports = { * Check indent for node * @param {ASTNode} node Node to check * @param {int} neededIndent needed indent - * @param {boolean} [excludeCommas=false] skip comma on start of line * @returns {void} */ function checkNodeIndent(node, neededIndent) { @@ -64859,7 +71970,6 @@ module.exports = { * Check indent for nodes list * @param {ASTNode[]} nodes list of node objects * @param {int} indent needed indent - * @param {boolean} [excludeCommas=false] skip comma on start of line * @returns {void} */ function checkNodesIndent(nodes, indent) { @@ -64936,12 +72046,9 @@ module.exports = { */ function getParentNodeByType(node, type, stopAtList) { var parent = node.parent; + var stopAtSet = new Set(stopAtList || ["Program"]); - if (!stopAtList) { - stopAtList = ["Program"]; - } - - while (parent.type !== type && stopAtList.indexOf(parent.type) === -1 && parent.type !== "Program") { + while (parent.type !== type && !stopAtSet.has(parent.type) && parent.type !== "Program") { parent = parent.parent; } @@ -65340,19 +72447,17 @@ module.exports = { /** * Returns the expected indentation for the case statement * @param {ASTNode} node node to examine - * @param {int} [switchIndent] indent for switch statement + * @param {int} [providedSwitchIndent] indent for switch statement * @returns {int} indent size */ - function expectedCaseIndent(node, switchIndent) { + function expectedCaseIndent(node, providedSwitchIndent) { var switchNode = node.type === "SwitchStatement" ? node : node.parent; + var switchIndent = typeof providedSwitchIndent === "undefined" ? getNodeIndent(switchNode).goodChar : providedSwitchIndent; var caseIndent = void 0; if (caseIndentStore[switchNode.loc.start.line]) { return caseIndentStore[switchNode.loc.start.line]; } - if (typeof switchIndent === "undefined") { - switchIndent = getNodeIndent(switchNode).goodChar; - } if (switchNode.cases.length > 0 && options.SwitchCase === 0) { caseIndent = switchIndent; @@ -65521,9 +72626,9 @@ module.exports = { } }; -},{"../ast-utils":115}],175:[function(require,module,exports){ +},{"../util/ast-utils":405}],170:[function(require,module,exports){ /** - * @fileoverview This option sets a specific tab width for your code + * @fileoverview This rule sets a specific indentation style and width for your code * * @author Teddy Katz * @author Vitaly Puzrin @@ -65543,7 +72648,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var createTree = require("functional-red-black-tree"); //------------------------------------------------------------------------------ @@ -65983,6 +73088,8 @@ var ELEMENT_LIST_SCHEMA = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent indentation", category: "Stylistic Issues", @@ -66007,24 +73114,12 @@ module.exports = { minimum: 0 }, VariableDeclarator: { - oneOf: [{ - type: "integer", - minimum: 0 - }, { + oneOf: [ELEMENT_LIST_SCHEMA, { type: "object", properties: { - var: { - type: "integer", - minimum: 0 - }, - let: { - type: "integer", - minimum: 0 - }, - const: { - type: "integer", - minimum: 0 - } + var: ELEMENT_LIST_SCHEMA, + let: ELEMENT_LIST_SCHEMA, + const: ELEMENT_LIST_SCHEMA }, additionalProperties: false }] @@ -66140,7 +73235,7 @@ module.exports = { if (context.options[1]) { lodash.merge(options, context.options[1]); - if (typeof options.VariableDeclarator === "number") { + if (typeof options.VariableDeclarator === "number" || options.VariableDeclarator === "first") { options.VariableDeclarator = { var: options.VariableDeclarator, let: options.VariableDeclarator, @@ -66258,6 +73353,19 @@ module.exports = { return (statement.type === "ExpressionStatement" || statement.type === "VariableDeclaration") && statement.parent.type === "Program"; } + /** + * Counts the number of linebreaks that follow the last non-whitespace character in a string + * @param {string} string The string to check + * @returns {number} The number of JavaScript linebreaks that follow the last non-whitespace character, + * or the total number of linebreaks if the string is all whitespace. + */ + function countTrailingLinebreaks(string) { + var trailingWhitespace = string.match(/\s*$/)[0]; + var linebreakMatches = trailingWhitespace.match(astUtils.createGlobalLinebreakMatcher()); + + return linebreakMatches === null ? 0 : linebreakMatches.length; + } + /** * Check indentation for lists of elements (arrays, objects, function params) * @param {ASTNode[]} elements List of elements that should be offset @@ -66311,9 +73419,10 @@ module.exports = { } else { var previousElement = elements[index - 1]; var firstTokenOfPreviousElement = previousElement && getFirstToken(previousElement); + var previousElementLastToken = previousElement && sourceCode.getLastToken(previousElement); - if (previousElement && sourceCode.getLastToken(previousElement).loc.end.line > startToken.loc.end.line) { - offsets.setDesiredOffsets(element.range, firstTokenOfPreviousElement, 0); + if (previousElement && previousElementLastToken.loc.end.line - countTrailingLinebreaks(previousElementLastToken.value) > startToken.loc.end.line) { + offsets.setDesiredOffsets([previousElement.range[1], element.range[1]], firstTokenOfPreviousElement, 0); } } }); @@ -66452,6 +73561,33 @@ module.exports = { return !node || node.loc.start.line === token.loc.start.line; } + /** + * Check whether there are any blank (whitespace-only) lines between + * two tokens on separate lines. + * @param {Token} firstToken The first token. + * @param {Token} secondToken The second token. + * @returns {boolean} `true` if the tokens are on separate lines and + * there exists a blank line between them, `false` otherwise. + */ + function hasBlankLinesBetween(firstToken, secondToken) { + var firstTokenLine = firstToken.loc.end.line; + var secondTokenLine = secondToken.loc.start.line; + + if (firstTokenLine === secondTokenLine || firstTokenLine === secondTokenLine - 1) { + return false; + } + + for (var line = firstTokenLine + 1; line < secondTokenLine; ++line) { + if (!tokenInfo.firstTokensByLineNumber.has(line)) { + return true; + } + } + + return false; + } + + var ignoredNodeFirstTokens = new Set(); + var baseOffsetListeners = { "ArrayExpression, ArrayPattern": function ArrayExpressionArrayPattern(node) { var openingBracket = sourceCode.getFirstToken(node); @@ -66477,15 +73613,6 @@ module.exports = { addElementListIndent(node.params, openingParen, closingParen, options.FunctionExpression.parameters); } addBlocklessNodeIndent(node.body); - - var arrowToken = void 0; - - if (node.params.length) { - arrowToken = sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isArrowToken); - } else { - arrowToken = sourceCode.getFirstToken(node, astUtils.isArrowToken); - } - offsets.setDesiredOffset(arrowToken, sourceCode.getFirstToken(node), 0); }, AssignmentExpression: function AssignmentExpression(node) { var operator = sourceCode.getFirstTokenBetween(node.left, node.right, function (token) { @@ -66596,9 +73723,6 @@ module.exports = { */ offsets.setDesiredOffset(firstAlternateToken, firstToken, 1); } - - offsets.setDesiredOffsets([questionMarkToken.range[1], colonToken.range[0]], firstConsequentToken, 0); - offsets.setDesiredOffsets([colonToken.range[1], node.range[1]], firstAlternateToken, 0); } }, @@ -66664,9 +73788,17 @@ module.exports = { var fromToken = sourceCode.getLastToken(node, function (token) { return token.type === "Identifier" && token.value === "from"; }); + var sourceToken = sourceCode.getLastToken(node, function (token) { + return token.type === "String"; + }); + var semiToken = sourceCode.getLastToken(node, function (token) { + return token.type === "Punctuator" && token.value === ";"; + }); if (fromToken) { - offsets.setDesiredOffsets([fromToken.range[0], node.range[1]], sourceCode.getFirstToken(node), 1); + var end = semiToken && semiToken.range[1] === sourceToken.range[1] ? node.range[1] : sourceToken.range[1]; + + offsets.setDesiredOffsets([fromToken.range[0], end], sourceCode.getFirstToken(node), 1); } }, "MemberExpression, JSXMemberExpression, MetaProperty": function MemberExpressionJSXMemberExpressionMetaProperty(node) { @@ -66735,28 +73867,23 @@ module.exports = { SwitchStatement: function SwitchStatement(node) { var openingCurly = sourceCode.getTokenAfter(node.discriminant, astUtils.isOpeningBraceToken); var closingCurly = sourceCode.getLastToken(node); - var caseKeywords = node.cases.map(function (switchCase) { - return sourceCode.getFirstToken(switchCase); - }); offsets.setDesiredOffsets([openingCurly.range[1], closingCurly.range[0]], openingCurly, options.SwitchCase); - node.cases.forEach(function (switchCase, index) { - var caseKeyword = caseKeywords[index]; - - if (!(switchCase.consequent.length === 1 && switchCase.consequent[0].type === "BlockStatement")) { - var tokenAfterCurrentCase = index === node.cases.length - 1 ? closingCurly : caseKeywords[index + 1]; - - offsets.setDesiredOffsets([caseKeyword.range[1], tokenAfterCurrentCase.range[0]], caseKeyword, 1); - } - }); - if (node.cases.length) { sourceCode.getTokensBetween(node.cases[node.cases.length - 1], closingCurly, { includeComments: true, filter: astUtils.isCommentToken }).forEach(function (token) { return offsets.ignoreToken(token); }); } }, + SwitchCase: function SwitchCase(node) { + if (!(node.consequent.length === 1 && node.consequent[0].type === "BlockStatement")) { + var caseKeyword = sourceCode.getFirstToken(node); + var tokenAfterCurrentCase = sourceCode.getTokenAfter(node); + + offsets.setDesiredOffsets([caseKeyword.range[1], tokenAfterCurrentCase.range[0]], caseKeyword, 1); + } + }, TemplateLiteral: function TemplateLiteral(node) { node.expressions.forEach(function (expression, index) { var previousQuasi = node.quasis[index]; @@ -66768,7 +73895,19 @@ module.exports = { }); }, VariableDeclaration: function VariableDeclaration(node) { - var variableIndent = options.VariableDeclarator.hasOwnProperty(node.kind) ? options.VariableDeclarator[node.kind] : DEFAULT_VARIABLE_INDENT; + var variableIndent = Object.prototype.hasOwnProperty.call(options.VariableDeclarator, node.kind) ? options.VariableDeclarator[node.kind] : DEFAULT_VARIABLE_INDENT; + + var firstToken = sourceCode.getFirstToken(node), + lastToken = sourceCode.getLastToken(node); + + if (options.VariableDeclarator[node.kind] === "first") { + if (node.declarations.length > 1) { + addElementListIndent(node.declarations, firstToken, lastToken, "first"); + return; + } + + variableIndent = DEFAULT_VARIABLE_INDENT; + } if (node.declarations[node.declarations.length - 1].loc.start.line > node.loc.start.line) { @@ -66791,13 +73930,10 @@ module.exports = { * on the same line as the start of the declaration, provided that there are declarators that * follow this one. */ - var firstToken = sourceCode.getFirstToken(node); - offsets.setDesiredOffsets(node.range, firstToken, variableIndent, true); } else { - offsets.setDesiredOffsets(node.range, sourceCode.getFirstToken(node), variableIndent); + offsets.setDesiredOffsets(node.range, firstToken, variableIndent); } - var lastToken = sourceCode.getLastToken(node); if (astUtils.isSemicolonToken(lastToken)) { offsets.ignoreToken(lastToken); @@ -66843,14 +73979,20 @@ module.exports = { var firstToken = sourceCode.getFirstToken(node); offsets.setDesiredOffsets(node.name.range, firstToken, 1); - offsets.setDesiredOffset(sourceCode.getLastToken(node), firstToken, 0); }, JSXExpressionContainer: function JSXExpressionContainer(node) { var openingCurly = sourceCode.getFirstToken(node); var closingCurly = sourceCode.getLastToken(node); offsets.setDesiredOffsets([openingCurly.range[1], closingCurly.range[0]], openingCurly, 1); - offsets.setDesiredOffset(closingCurly, openingCurly, 0); + }, + "*": function _(node) { + var firstToken = sourceCode.getFirstToken(node); + + // Ensure that the children of every node are indented at least as much as the first token. + if (firstToken && !ignoredNodeFirstTokens.has(firstToken)) { + offsets.setDesiredOffsets(node.range, firstToken, 0); + } } }; @@ -66859,7 +74001,8 @@ module.exports = { /* * To ignore the indentation of a node: * 1. Don't call the node's listener when entering it (if it has a listener) - * 2. Call `ignoreNode` on the node sometime after exiting it and before validating offsets. + * 2. Don't set any offsets against the first token of the node. + * 3. Call `ignoreNode` on the node sometime after exiting it and before validating offsets. */ var offsetListeners = lodash.mapValues(baseOffsetListeners, @@ -66887,7 +74030,16 @@ module.exports = { // For each ignored node selector, set up a listener to collect it into the `ignoredNodes` set. var ignoredNodes = new Set(); - var addToIgnoredNodes = ignoredNodes.add.bind(ignoredNodes); + + /** + * Ignores a node + * @param {ASTNode} node The node to ignore + * @returns {void} + */ + function addToIgnoredNodes(node) { + ignoredNodes.add(node); + ignoredNodeFirstTokens.add(sourceCode.getFirstToken(node)); + } var ignoredNodeListeners = options.ignoredNodes.reduce(function (listeners, ignoredSelector) { return Object.assign(listeners, _defineProperty({}, ignoredSelector, addToIgnoredNodes)); @@ -66906,7 +74058,7 @@ module.exports = { // If a node's type is nonstandard, we can't tell how its children should be offset, so ignore it. if (!KNOWN_NODES.has(node.type)) { - ignoredNodes.add(node); + addToIgnoredNodes(node); } }, "Program:exit": function ProgramExit() { @@ -66966,8 +74118,11 @@ module.exports = { var tokenBefore = precedingTokens.get(firstTokenOfLine); var tokenAfter = tokenBefore ? sourceCode.getTokenAfter(tokenBefore) : sourceCode.ast.tokens[0]; + var mayAlignWithBefore = tokenBefore && !hasBlankLinesBetween(tokenBefore, firstTokenOfLine); + var mayAlignWithAfter = tokenAfter && !hasBlankLinesBetween(firstTokenOfLine, tokenAfter); + // If a comment matches the expected indentation of the token immediately before or after, don't report it. - if (tokenBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) || tokenAfter && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenAfter))) { + if (mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) || mayAlignWithAfter && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenAfter))) { return; } } @@ -66980,7 +74135,7 @@ module.exports = { } }; -},{"../ast-utils":115,"functional-red-black-tree":81,"lodash":89}],176:[function(require,module,exports){ +},{"../util/ast-utils":405,"functional-red-black-tree":83,"lodash":92}],171:[function(require,module,exports){ /** * @fileoverview A rule to control the style of variable initializations. * @author Colin Ihrig @@ -67026,6 +74181,8 @@ function isInitialized(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow initialization in variable declarations", category: "Variables", @@ -67111,7 +74268,7 @@ module.exports = { } }; -},{}],177:[function(require,module,exports){ +},{}],172:[function(require,module,exports){ /** * @fileoverview A rule to ensure consistent quotes used in jsx syntax. * @author Mathias Schreck @@ -67123,7 +74280,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Constants @@ -67152,6 +74309,8 @@ var QUOTE_SETTINGS = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce the consistent use of either double or single quotes in JSX attributes", category: "Stylistic Issues", @@ -67201,7 +74360,7 @@ module.exports = { } }; -},{"../ast-utils":115}],178:[function(require,module,exports){ +},{"../util/ast-utils":405}],173:[function(require,module,exports){ /** * @fileoverview Rule to specify spacing of object literal keys and values * @author Brandon Mills @@ -67214,7 +74373,9 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -67335,6 +74496,8 @@ var messages = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing between keys and values in object literal properties", category: "Stylistic Issues", @@ -67552,8 +74715,7 @@ module.exports = { * @returns {boolean} Whether the property is a key-value property. */ function isKeyValueProperty(property) { - return !(property.method || property.shorthand || property.kind !== "init" || property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadElement" - ); + return !(property.method || property.shorthand || property.kind !== "init" || property.type !== "Property"); } /** @@ -67721,7 +74883,7 @@ module.exports = { widths = properties.map(getKeyWidth), // Width of keys, including quotes align = alignmentOptions.on; // "value" or "colon" - var targetWidth = Math.max.apply(null, widths), + var targetWidth = Math.max.apply(Math, _toConsumableArray(widths)), beforeColon = void 0, afterColon = void 0, mode = void 0; @@ -67827,7 +74989,7 @@ module.exports = { } }; -},{"../ast-utils":115}],179:[function(require,module,exports){ +},{"../util/ast-utils":405}],174:[function(require,module,exports){ /** * @fileoverview Rule to enforce spacing before and after keywords. * @author Toru Nagashima @@ -67839,7 +75001,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"), +var astUtils = require("../util/ast-utils"), keywords = require("../util/keywords"); //------------------------------------------------------------------------------ @@ -67895,6 +75057,8 @@ function isCloseParenOfTemplate(token) { module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before and after keywords", category: "Stylistic Issues", @@ -67936,13 +75100,10 @@ module.exports = { * Reports a given token if there are not space(s) before the token. * * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the previous - * token to check. + * @param {RegExp} pattern - A pattern of the previous token to check. * @returns {void} */ function expectSpaceBefore(token, pattern) { - pattern = pattern || PREV_TOKEN; - var prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && !isOpenParenOfTemplate(prevToken) && astUtils.isTokenOnSameLine(prevToken, token) && !sourceCode.isSpaceBetweenTokens(prevToken, token)) { @@ -67961,13 +75122,10 @@ module.exports = { * Reports a given token if there are space(s) before the token. * * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the previous - * token to check. + * @param {RegExp} pattern - A pattern of the previous token to check. * @returns {void} */ function unexpectSpaceBefore(token, pattern) { - pattern = pattern || PREV_TOKEN; - var prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && !isOpenParenOfTemplate(prevToken) && astUtils.isTokenOnSameLine(prevToken, token) && sourceCode.isSpaceBetweenTokens(prevToken, token)) { @@ -67986,13 +75144,10 @@ module.exports = { * Reports a given token if there are not space(s) after the token. * * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the next - * token to check. + * @param {RegExp} pattern - A pattern of the next token to check. * @returns {void} */ function expectSpaceAfter(token, pattern) { - pattern = pattern || NEXT_TOKEN; - var nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && !isCloseParenOfTemplate(nextToken) && astUtils.isTokenOnSameLine(token, nextToken) && !sourceCode.isSpaceBetweenTokens(token, nextToken)) { @@ -68011,13 +75166,10 @@ module.exports = { * Reports a given token if there are space(s) after the token. * * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the next - * token to check. + * @param {RegExp} pattern - A pattern of the next token to check. * @returns {void} */ function unexpectSpaceAfter(token, pattern) { - pattern = pattern || NEXT_TOKEN; - var nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && !isCloseParenOfTemplate(nextToken) && astUtils.isTokenOnSameLine(token, nextToken) && sourceCode.isSpaceBetweenTokens(token, nextToken)) { @@ -68082,7 +75234,7 @@ module.exports = { * @returns {void} */ function checkSpacingBefore(token, pattern) { - checkMethodMap[token.value].before(token, pattern); + checkMethodMap[token.value].before(token, pattern || PREV_TOKEN); } /** @@ -68095,7 +75247,7 @@ module.exports = { * @returns {void} */ function checkSpacingAfter(token, pattern) { - checkMethodMap[token.value].after(token, pattern); + checkMethodMap[token.value].after(token, pattern || NEXT_TOKEN); } /** @@ -68268,6 +75420,10 @@ module.exports = { checkSpacingBefore(firstToken, PREV_TOKEN_M); checkSpacingAfter(firstToken, NEXT_TOKEN_M); + if (node.type === "ExportDefaultDeclaration") { + checkSpacingAround(sourceCode.getTokenAfter(firstToken)); + } + if (node.source) { var fromToken = sourceCode.getTokenBefore(node.source); @@ -68359,7 +75515,7 @@ module.exports = { // Statements - Declarations ClassDeclaration: checkSpacingForClass, ExportNamedDeclaration: checkSpacingForModuleDeclaration, - ExportDefaultDeclaration: checkSpacingAroundFirstToken, + ExportDefaultDeclaration: checkSpacingForModuleDeclaration, ExportAllDeclaration: checkSpacingForModuleDeclaration, FunctionDeclaration: checkSpacingForFunction, ImportDeclaration: checkSpacingForModuleDeclaration, @@ -68384,14 +75540,14 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/keywords":405}],180:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/keywords":409}],175:[function(require,module,exports){ /** * @fileoverview Rule to enforce the position of line comments * @author Alberto Rodríguez */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -68399,6 +75555,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce position of line comments", category: "Stylistic Issues", @@ -68440,10 +75598,10 @@ module.exports = { if (!options || typeof options === "string") { above = !options || options === "above"; } else { - above = options.position === "above"; + above = !options.position || options.position === "above"; ignorePattern = options.ignorePattern; - if (options.hasOwnProperty("applyDefaultIgnorePatterns")) { + if (Object.prototype.hasOwnProperty.call(options, "applyDefaultIgnorePatterns")) { applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false; } else { applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false; @@ -68498,7 +75656,7 @@ module.exports = { } }; -},{"../ast-utils":115}],181:[function(require,module,exports){ +},{"../util/ast-utils":405}],176:[function(require,module,exports){ /** * @fileoverview Rule to enforce a single linebreak style. * @author Erik Mueller @@ -68510,7 +75668,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -68518,6 +75676,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent linebreak style", category: "Stylistic Issues", @@ -68595,7 +75755,7 @@ module.exports = { } }; -},{"../ast-utils":115}],182:[function(require,module,exports){ +},{"../util/ast-utils":405}],177:[function(require,module,exports){ /** * @fileoverview Enforces empty lines around comments. * @author Jamund Ferguson @@ -68607,7 +75767,7 @@ module.exports = { //------------------------------------------------------------------------------ var lodash = require("lodash"), - astUtils = require("../ast-utils"); + astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -68656,6 +75816,8 @@ function getCommentLineNums(comments) { module.exports = { meta: { + type: "layout", + docs: { description: "require empty lines around comments", category: "Stylistic Issues", @@ -68988,7 +76150,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],183:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],178:[function(require,module,exports){ /** * @fileoverview Require or disallow newlines around directives. * @author Kai Cataldo @@ -68997,7 +76159,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -69005,13 +76167,15 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow newlines around directives", category: "Stylistic Issues", recommended: false, - replacedBy: ["padding-line-between-statements"], url: "https://eslint.org/docs/rules/lines-around-directive" }, + schema: [{ oneOf: [{ enum: ["always", "never"] @@ -69029,8 +76193,10 @@ module.exports = { minProperties: 2 }] }], + fixable: "whitespace", - deprecated: true + deprecated: true, + replacedBy: ["padding-line-between-statements"] }, create: function create(context) { @@ -69174,14 +76340,14 @@ module.exports = { } }; -},{"../ast-utils":115}],184:[function(require,module,exports){ +},{"../util/ast-utils":405}],179:[function(require,module,exports){ /** * @fileoverview Rule to check empty newline between class members * @author 薛定谔的猫 */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -69189,6 +76355,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow an empty line between class members", category: "Stylistic Issues", @@ -69312,7 +76480,71 @@ module.exports = { } }; -},{"../ast-utils":115}],185:[function(require,module,exports){ +},{"../util/ast-utils":405}],180:[function(require,module,exports){ +/** + * @fileoverview Enforce a maximum number of classes per file + * @author James Garbutt + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "enforce a maximum number of classes per file", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/max-classes-per-file" + }, + + schema: [{ + type: "integer", + minimum: 1 + }], + + messages: { + maximumExceeded: "Number of classes per file must not exceed {{ max }}" + } + }, + create: function create(context) { + + var maxClasses = context.options[0] || 1; + + var classCount = 0; + + return { + Program: function Program() { + classCount = 0; + }, + "Program:exit": function ProgramExit(node) { + if (classCount > maxClasses) { + context.report({ + node: node, + messageId: "maximumExceeded", + data: { + max: maxClasses + } + }); + } + }, + "ClassDeclaration, ClassExpression": function ClassDeclarationClassExpression() { + classCount++; + } + }; + } +}; + +},{}],181:[function(require,module,exports){ /** * @fileoverview A rule to set the maximum depth block can be nested in a function. * @author Ian Christian Myers @@ -69328,6 +76560,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum depth that blocks can be nested", category: "Stylistic Issues", @@ -69366,10 +76600,10 @@ module.exports = { option = context.options[0]; var maxDepth = 4; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") { maxDepth = option.maximum; } - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { maxDepth = option.max; } if (typeof option === "number") { @@ -69460,7 +76694,7 @@ module.exports = { } }; -},{}],186:[function(require,module,exports){ +},{}],182:[function(require,module,exports){ /** * @fileoverview Rule to check for max length on a line. * @author Matt DuVall @@ -69527,6 +76761,8 @@ var OPTIONS_OR_INTEGER_SCHEMA = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce a maximum line length", category: "Stylistic Issues", @@ -69668,7 +76904,7 @@ module.exports = { */ function getAllStrings() { return sourceCode.ast.tokens.filter(function (token) { - return token.type === "String"; + return token.type === "String" || token.type === "JSXText" && sourceCode.getNodeByRangeIndex(token.range[0] - 1).type === "JSXAttribute"; }); } @@ -69746,6 +76982,7 @@ module.exports = { * line is a comment */ var lineIsComment = false; + var textToMeasure = void 0; /* * We can short-circuit the comment checks if we're already out of @@ -69764,17 +77001,22 @@ module.exports = { if (isFullLineComment(line, lineNumber, comment)) { lineIsComment = true; + textToMeasure = line; } else if (ignoreTrailingComments && isTrailingComment(line, lineNumber, comment)) { - line = stripTrailingComment(line, comment); + textToMeasure = stripTrailingComment(line, comment); + } else { + textToMeasure = line; } + } else { + textToMeasure = line; } - if (ignorePattern && ignorePattern.test(line) || ignoreUrls && URL_REGEXP.test(line) || ignoreStrings && stringsByLine[lineNumber] || ignoreTemplateLiterals && templateLiteralsByLine[lineNumber] || ignoreRegExpLiterals && regExpLiteralsByLine[lineNumber]) { + if (ignorePattern && ignorePattern.test(textToMeasure) || ignoreUrls && URL_REGEXP.test(textToMeasure) || ignoreStrings && stringsByLine[lineNumber] || ignoreTemplateLiterals && templateLiteralsByLine[lineNumber] || ignoreRegExpLiterals && regExpLiteralsByLine[lineNumber]) { // ignore this line return; } - var lineLength = computeLineLength(line, tabWidth); + var lineLength = computeLineLength(textToMeasure, tabWidth); var commentLengthApplies = lineIsComment && maxCommentLength; if (lineIsComment && ignoreComments) { @@ -69817,7 +77059,224 @@ module.exports = { } }; -},{}],187:[function(require,module,exports){ +},{}],183:[function(require,module,exports){ +/** + * @fileoverview A rule to set the maximum number of line of code in a function. + * @author Pete Ward + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var astUtils = require("../util/ast-utils"); + +//------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------ + +var OPTIONS_SCHEMA = { + type: "object", + properties: { + max: { + type: "integer", + minimum: 0 + }, + skipComments: { + type: "boolean" + }, + skipBlankLines: { + type: "boolean" + }, + IIFEs: { + type: "boolean" + } + }, + additionalProperties: false +}; + +var OPTIONS_OR_INTEGER_SCHEMA = { + oneOf: [OPTIONS_SCHEMA, { + type: "integer", + minimum: 1 + }] +}; + +/** + * Given a list of comment nodes, return a map with numeric keys (source code line numbers) and comment token values. + * @param {Array} comments An array of comment nodes. + * @returns {Map.} A map with numeric keys (source code line numbers) and comment token values. + */ +function getCommentLineNumbers(comments) { + var map = new Map(); + + if (!comments) { + return map; + } + comments.forEach(function (comment) { + for (var i = comment.loc.start.line; i <= comment.loc.end.line; i++) { + map.set(i, comment); + } + }); + return map; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "enforce a maximum number of line of code in a function", + category: "Stylistic Issues", + recommended: false, + url: "https://eslint.org/docs/rules/max-lines-per-function" + }, + + schema: [OPTIONS_OR_INTEGER_SCHEMA] + }, + + create: function create(context) { + var sourceCode = context.getSourceCode(); + var lines = sourceCode.lines; + + var option = context.options[0]; + var maxLines = 50; + var skipComments = false; + var skipBlankLines = false; + var IIFEs = false; + + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object") { + if (typeof option.max === "number") { + maxLines = option.max; + } + if (typeof option.skipComments === "boolean") { + skipComments = option.skipComments; + } + if (typeof option.skipBlankLines === "boolean") { + skipBlankLines = option.skipBlankLines; + } + if (typeof option.IIFEs === "boolean") { + IIFEs = option.IIFEs; + } + } else if (typeof option === "number") { + maxLines = option; + } + + var commentLineNumbers = getCommentLineNumbers(sourceCode.getAllComments()); + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Tells if a comment encompasses the entire line. + * @param {string} line The source line with a trailing comment + * @param {number} lineNumber The one-indexed line number this is on + * @param {ASTNode} comment The comment to remove + * @returns {boolean} If the comment covers the entire line + */ + function isFullLineComment(line, lineNumber, comment) { + var start = comment.loc.start, + end = comment.loc.end, + isFirstTokenOnLine = start.line === lineNumber && !line.slice(0, start.column).trim(), + isLastTokenOnLine = end.line === lineNumber && !line.slice(end.column).trim(); + + return comment && (start.line < lineNumber || isFirstTokenOnLine) && (end.line > lineNumber || isLastTokenOnLine); + } + + /** + * Identifies is a node is a FunctionExpression which is part of an IIFE + * @param {ASTNode} node Node to test + * @returns {boolean} True if it's an IIFE + */ + function isIIFE(node) { + return node.type === "FunctionExpression" && node.parent && node.parent.type === "CallExpression" && node.parent.callee === node; + } + + /** + * Identifies is a node is a FunctionExpression which is embedded within a MethodDefinition or Property + * @param {ASTNode} node Node to test + * @returns {boolean} True if it's a FunctionExpression embedded within a MethodDefinition or Property + */ + function isEmbedded(node) { + if (!node.parent) { + return false; + } + if (node !== node.parent.value) { + return false; + } + if (node.parent.type === "MethodDefinition") { + return true; + } + if (node.parent.type === "Property") { + return node.parent.method === true || node.parent.kind === "get" || node.parent.kind === "set"; + } + return false; + } + + /** + * Count the lines in the function + * @param {ASTNode} funcNode Function AST node + * @returns {void} + * @private + */ + function processFunction(funcNode) { + var node = isEmbedded(funcNode) ? funcNode.parent : funcNode; + + if (!IIFEs && isIIFE(node)) { + return; + } + var lineCount = 0; + + for (var i = node.loc.start.line - 1; i < node.loc.end.line; ++i) { + var line = lines[i]; + + if (skipComments) { + if (commentLineNumbers.has(i + 1) && isFullLineComment(line, i + 1, commentLineNumbers.get(i + 1))) { + continue; + } + } + + if (skipBlankLines) { + if (line.match(/^\s*$/)) { + continue; + } + } + + lineCount++; + } + + if (lineCount > maxLines) { + var name = astUtils.getFunctionNameWithKind(funcNode); + + context.report({ + node: node, + message: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}.", + data: { name: name, lineCount: lineCount, maxLines: maxLines } + }); + } + } + + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + FunctionDeclaration: processFunction, + FunctionExpression: processFunction, + ArrowFunctionExpression: processFunction + }; + } +}; + +},{"../util/ast-utils":405}],184:[function(require,module,exports){ /** * @fileoverview enforce a maximum file length * @author Alberto Rodríguez @@ -69831,7 +77290,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -69839,6 +77298,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum number of lines per file", category: "Stylistic Issues", @@ -69873,7 +77334,7 @@ module.exports = { var option = context.options[0]; var max = 300; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { max = option.max; } @@ -69969,7 +77430,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],188:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],185:[function(require,module,exports){ /** * @fileoverview Rule to enforce a maximum number of nested callbacks. * @author Ian Christian Myers @@ -69985,6 +77446,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum depth that callbacks can be nested", category: "Stylistic Issues", @@ -70021,10 +77484,10 @@ module.exports = { var option = context.options[0]; var THRESHOLD = 10; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") { THRESHOLD = option.maximum; } - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { THRESHOLD = option.max; } if (typeof option === "number") { @@ -70080,7 +77543,7 @@ module.exports = { } }; -},{}],189:[function(require,module,exports){ +},{}],186:[function(require,module,exports){ /** * @fileoverview Rule to flag when a function has too many parameters * @author Ilya Volodin @@ -70096,7 +77559,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -70104,6 +77567,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum number of parameters in function definitions", category: "Stylistic Issues", @@ -70133,14 +77598,14 @@ module.exports = { }, create: function create(context) { - + var sourceCode = context.getSourceCode(); var option = context.options[0]; var numParams = 3; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") { numParams = option.maximum; } - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { numParams = option.max; } if (typeof option === "number") { @@ -70156,6 +77621,7 @@ module.exports = { function checkFunction(node) { if (node.params.length > numParams) { context.report({ + loc: astUtils.getFunctionHeadLoc(node, sourceCode), node: node, message: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}.", data: { @@ -70175,7 +77641,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],190:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],187:[function(require,module,exports){ /** * @fileoverview Specify the maximum number of statements allowed per line. * @author Kenneth Williams @@ -70186,7 +77652,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -70194,6 +77660,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce a maximum number of statements allowed per line", category: "Stylistic Issues", @@ -70368,7 +77836,7 @@ module.exports = { } }; -},{"../ast-utils":115}],191:[function(require,module,exports){ +},{"../util/ast-utils":405}],188:[function(require,module,exports){ /** * @fileoverview A rule to set the maximum number of statements in a function. * @author Ian Christian Myers @@ -70384,7 +77852,7 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -70392,6 +77860,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a maximum number of statements allowed in function blocks", category: "Stylistic Issues", @@ -70440,10 +77910,10 @@ module.exports = { topLevelFunctions = []; var maxStatements = 10; - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "maximum") && typeof option.maximum === "number") { maxStatements = option.maximum; } - if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + if ((typeof option === "undefined" ? "undefined" : _typeof(option)) === "object" && Object.prototype.hasOwnProperty.call(option, "max") && typeof option.max === "number") { maxStatements = option.max; } if (typeof option === "number") { @@ -70536,14 +78006,14 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],192:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],189:[function(require,module,exports){ /** * @fileoverview enforce a particular style for multiline comments * @author Teddy Katz */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -70551,12 +78021,15 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce a particular style for multiline comments", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/multiline-comment-style" }, + fixable: "whitespace", schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }] }, @@ -70856,7 +78329,7 @@ module.exports = { } }; -},{"../ast-utils":115}],193:[function(require,module,exports){ +},{"../util/ast-utils":405}],190:[function(require,module,exports){ /** * @fileoverview Enforce newlines between operands of ternary expressions * @author Kai Cataldo @@ -70864,7 +78337,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -70872,12 +78345,15 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce newlines between operands of ternary expressions", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/multiline-ternary" }, + schema: [{ enum: ["always", "always-multiline", "never"] }] @@ -70946,7 +78422,7 @@ module.exports = { } }; -},{"../ast-utils":115}],194:[function(require,module,exports){ +},{"../util/ast-utils":405}],191:[function(require,module,exports){ /** * @fileoverview Rule to flag use of constructors without capital letters * @author Nicholas C. Zakas @@ -71012,6 +78488,8 @@ function calculateCapIsNewExceptions(config) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require constructor names to begin with a capital letter", category: "Stylistic Issues", @@ -71206,7 +78684,7 @@ module.exports = { } }; -},{}],195:[function(require,module,exports){ +},{}],192:[function(require,module,exports){ /** * @fileoverview Rule to flag when using constructor without parentheses * @author Ilya Volodin @@ -71218,7 +78696,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -71230,6 +78708,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require parentheses when invoking a constructor with no arguments", category: "Stylistic Issues", @@ -71238,7 +78718,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -71269,7 +78748,7 @@ module.exports = { } }; -},{"../ast-utils":115}],196:[function(require,module,exports){ +},{"../util/ast-utils":405}],193:[function(require,module,exports){ /** * @fileoverview Rule to check empty newline after "var" statement * @author Gopal Venkatesan @@ -71282,7 +78761,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -71290,11 +78769,12 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow an empty line after variable declarations", category: "Stylistic Issues", recommended: false, - replacedBy: ["padding-line-between-statements"], url: "https://eslint.org/docs/rules/newline-after-var" }, @@ -71304,7 +78784,9 @@ module.exports = { fixable: "whitespace", - deprecated: true + deprecated: true, + + replacedBy: ["padding-line-between-statements"] }, create: function create(context) { @@ -71517,7 +78999,7 @@ module.exports = { } }; -},{"../ast-utils":115}],197:[function(require,module,exports){ +},{"../util/ast-utils":405}],194:[function(require,module,exports){ /** * @fileoverview Rule to require newlines before `return` statement * @author Kai Cataldo @@ -71531,16 +79013,19 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require an empty line before `return` statements", category: "Stylistic Issues", recommended: false, - replacedBy: ["padding-line-between-statements"], url: "https://eslint.org/docs/rules/newline-before-return" }, + fixable: "whitespace", schema: [], - deprecated: true + deprecated: true, + replacedBy: ["padding-line-between-statements"] }, create: function create(context) { @@ -71553,7 +79038,7 @@ module.exports = { /** * Tests whether node is preceded by supplied tokens * @param {ASTNode} node - node to check - * @param {array} testTokens - array of tokens to test against + * @param {Array} testTokens - array of tokens to test against * @returns {boolean} Whether or not the node is preceded by one of the supplied tokens * @private */ @@ -71728,7 +79213,7 @@ module.exports = { } }; -},{}],198:[function(require,module,exports){ +},{}],195:[function(require,module,exports){ /** * @fileoverview Rule to ensure newline per method call when chaining calls * @author Rajendra Patil @@ -71737,7 +79222,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -71745,13 +79230,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require a newline after each call in a method chain", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/newline-per-chained-call" }, + fixable: "whitespace", + schema: [{ type: "object", properties: { @@ -71834,7 +79323,7 @@ module.exports = { } }; -},{"../ast-utils":115}],199:[function(require,module,exports){ +},{"../util/ast-utils":405}],196:[function(require,module,exports){ /** * @fileoverview Rule to flag use of alert, confirm, prompt * @author Nicholas C. Zakas @@ -71845,7 +79334,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var getPropertyName = require("../ast-utils").getStaticPropertyName; +var getPropertyName = require("../util/ast-utils").getStaticPropertyName; //------------------------------------------------------------------------------ // Helpers @@ -71913,6 +79402,8 @@ function isGlobalThisReferenceOrGlobalWindow(scope, node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `alert`, `confirm`, and `prompt`", category: "Best Practices", @@ -71960,7 +79451,7 @@ module.exports = { } }; -},{"../ast-utils":115}],200:[function(require,module,exports){ +},{"../util/ast-utils":405}],197:[function(require,module,exports){ /** * @fileoverview Disallow construction of dense arrays using the Array constructor * @author Matt DuVall @@ -71974,6 +79465,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `Array` constructors", category: "Stylistic Issues", @@ -72009,7 +79502,47 @@ module.exports = { } }; -},{}],201:[function(require,module,exports){ +},{}],198:[function(require,module,exports){ +/** + * @fileoverview disallow using an async function as a Promise executor + * @author Teddy Katz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow using an async function as a Promise executor", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/no-async-promise-executor" + }, + + fixable: null, + schema: [] + }, + + create: function create(context) { + return { + "NewExpression[callee.name='Promise'][arguments.0.async=true]": function NewExpressionCalleeNamePromiseArguments0AsyncTrue(node) { + context.report({ + node: context.getSourceCode().getFirstToken(node.arguments[0], function (token) { + return token.value === "async"; + }), + message: "Promise executor functions should not be async." + }); + } + }; + } +}; + +},{}],199:[function(require,module,exports){ /** * @fileoverview Rule to disallow uses of await inside of loops. * @author Nat Mote (nmote) @@ -72060,13 +79593,17 @@ function isLooped(node, parent) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow `await` inside of loops", category: "Possible Errors", recommended: false, url: "https://eslint.org/docs/rules/no-await-in-loop" }, + schema: [], + messages: { unexpectedAwait: "Unexpected `await` inside a loop." } @@ -72106,7 +79643,7 @@ module.exports = { } }; -},{}],202:[function(require,module,exports){ +},{}],200:[function(require,module,exports){ /** * @fileoverview Rule to flag bitwise identifiers * @author Nicholas C. Zakas @@ -72128,6 +79665,8 @@ var BITWISE_OPERATORS = ["^", "|", "&", "<<", ">>", ">>>", "^=", "|=", "&=", "<< module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow bitwise operators", category: "Stylistic Issues", @@ -72217,7 +79756,7 @@ module.exports = { } }; -},{}],203:[function(require,module,exports){ +},{}],201:[function(require,module,exports){ /** * @fileoverview disallow use of the Buffer() constructor * @author Teddy Katz @@ -72230,13 +79769,17 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { - description: "disallow use of the Buffer() constructor", + description: "disallow use of the `Buffer()` constructor", category: "Node.js and CommonJS", recommended: false, url: "https://eslint.org/docs/rules/no-buffer-constructor" }, + schema: [], + messages: { deprecated: "{{expr}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead." } @@ -72260,7 +79803,7 @@ module.exports = { } }; -},{}],204:[function(require,module,exports){ +},{}],202:[function(require,module,exports){ /** * @fileoverview Rule to flag use of arguments.callee and arguments.caller. * @author Nicholas C. Zakas @@ -72274,6 +79817,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `arguments.caller` or `arguments.callee`", category: "Best Practices", @@ -72303,7 +79848,7 @@ module.exports = { } }; -},{}],205:[function(require,module,exports){ +},{}],203:[function(require,module,exports){ /** * @fileoverview Rule to flag use of an lexical declarations inside a case clause * @author Erik Arvidsson @@ -72316,6 +79861,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow lexical declarations in case clauses", category: "Best Practices", @@ -72356,7 +79903,7 @@ module.exports = { if (isLexicalDeclaration(statement)) { context.report({ - node: node, + node: statement, messageId: "unexpected" }); } @@ -72366,10 +79913,11 @@ module.exports = { } }; -},{}],206:[function(require,module,exports){ +},{}],204:[function(require,module,exports){ /** * @fileoverview Rule to flag variable leak in CatchClauses in IE 8 and earlier * @author Ian Christian Myers + * @deprecated in ESLint v5.1.0 */ "use strict"; @@ -72378,7 +79926,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -72386,6 +79934,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `catch` clause parameters from shadowing variables in the outer scope", category: "Variables", @@ -72393,6 +79943,9 @@ module.exports = { url: "https://eslint.org/docs/rules/no-catch-shadow" }, + replacedBy: ["no-shadow"], + + deprecated: true, schema: [], messages: { @@ -72421,7 +79974,7 @@ module.exports = { //-------------------------------------------------------------------------- return { - CatchClause: function CatchClause(node) { + "CatchClause[param!=null]": function CatchClauseParamNull(node) { var scope = context.getScope(); /* @@ -72440,7 +79993,7 @@ module.exports = { } }; -},{"../ast-utils":115}],207:[function(require,module,exports){ +},{"../util/ast-utils":405}],205:[function(require,module,exports){ /** * @fileoverview A rule to disallow modifying variables of class declarations * @author Toru Nagashima @@ -72448,7 +80001,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -72456,6 +80009,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow reassigning class members", category: "ECMAScript 6", @@ -72499,7 +80054,7 @@ module.exports = { } }; -},{"../ast-utils":115}],208:[function(require,module,exports){ +},{"../util/ast-utils":405}],206:[function(require,module,exports){ /** * @fileoverview The rule should warn against code that tries to compare against -0. * @author Aladdin-ADD @@ -72512,14 +80067,18 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow comparing against -0", category: "Possible Errors", recommended: true, url: "https://eslint.org/docs/rules/no-compare-neg-zero" }, + fixable: null, schema: [], + messages: { unexpected: "Do not use the '{{operator}}' operator to compare against -0." } @@ -72558,14 +80117,14 @@ module.exports = { } }; -},{}],209:[function(require,module,exports){ +},{}],207:[function(require,module,exports){ /** * @fileoverview Rule to flag assignment in a conditional statement's test expression * @author Stephen Murray */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var NODE_DESCRIPTIONS = { DoWhileStatement: "a 'do...while' statement", @@ -72580,6 +80139,8 @@ var NODE_DESCRIPTIONS = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow assignment operators in conditional expressions", category: "Possible Errors", @@ -72688,12 +80249,13 @@ module.exports = { DoWhileStatement: testForAssign, ForStatement: testForAssign, IfStatement: testForAssign, - WhileStatement: testForAssign + WhileStatement: testForAssign, + ConditionalExpression: testForAssign }; } }; -},{"../ast-utils":115}],210:[function(require,module,exports){ +},{"../util/ast-utils":405}],208:[function(require,module,exports){ /** * @fileoverview A rule to warn against using arrow functions when they could be * confused with comparisions @@ -72702,7 +80264,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils.js"); +var astUtils = require("../util/ast-utils.js"); //------------------------------------------------------------------------------ // Helpers @@ -72723,6 +80285,8 @@ function isConditional(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow arrow functions where they could be confused with comparisons", category: "ECMAScript 6", @@ -72776,7 +80340,7 @@ module.exports = { } }; -},{"../ast-utils.js":115}],211:[function(require,module,exports){ +},{"../util/ast-utils.js":405}],209:[function(require,module,exports){ /** * @fileoverview Rule to flag use of console object * @author Nicholas C. Zakas @@ -72788,7 +80352,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -72796,6 +80360,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `console`", category: "Possible Errors", @@ -72904,7 +80470,7 @@ module.exports = { } }; -},{"../ast-utils":115}],212:[function(require,module,exports){ +},{"../util/ast-utils":405}],210:[function(require,module,exports){ /** * @fileoverview A rule to disallow modifying variables that are declared using `const` * @author Toru Nagashima @@ -72912,7 +80478,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -72920,6 +80486,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow reassigning `const` variables", category: "ECMAScript 6", @@ -72957,7 +80525,7 @@ module.exports = { } }; -},{"../ast-utils":115}],213:[function(require,module,exports){ +},{"../util/ast-utils":405}],211:[function(require,module,exports){ /** * @fileoverview Rule to flag use constant conditions * @author Christian Schulz @@ -72971,6 +80539,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow constant expressions in conditions", category: "Possible Errors", @@ -73125,7 +80695,6 @@ module.exports = { /** * Reports when the set still contains stored constant conditions - * @param {ASTNode} node The AST node to check. * @returns {void} * @private */ @@ -73163,6 +80732,8 @@ module.exports = { "ForStatement:exit": checkConstantConditionLoopInSet, FunctionDeclaration: enterFunction, "FunctionDeclaration:exit": exitFunction, + FunctionExpression: enterFunction, + "FunctionExpression:exit": exitFunction, YieldExpression: function YieldExpression() { return loopsInCurrentScope.clear(); } @@ -73170,7 +80741,7 @@ module.exports = { } }; -},{}],214:[function(require,module,exports){ +},{}],212:[function(require,module,exports){ /** * @fileoverview Rule to flag use of continue statement * @author Borislav Zhivkov @@ -73184,6 +80755,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `continue` statements", category: "Stylistic Issues", @@ -73208,7 +80781,7 @@ module.exports = { } }; -},{}],215:[function(require,module,exports){ +},{}],213:[function(require,module,exports){ /** * @fileoverview Rule to forbid control charactes from regular expressions. * @author Nicholas C. Zakas @@ -73216,12 +80789,58 @@ module.exports = { "use strict"; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var RegExpValidator = require("regexpp").RegExpValidator; +var collector = new (function () { + function _class() { + _classCallCheck(this, _class); + + this.ecmaVersion = 2018; + this._source = ""; + this._controlChars = []; + this._validator = new RegExpValidator(this); + } + + _createClass(_class, [{ + key: "onPatternEnter", + value: function onPatternEnter() { + this._controlChars = []; + } + }, { + key: "onCharacter", + value: function onCharacter(start, end, cp) { + if (cp >= 0x00 && cp <= 0x1F && (this._source.codePointAt(start) === cp || this._source.slice(start, end).startsWith("\\x") || this._source.slice(start, end).startsWith("\\u"))) { + this._controlChars.push("\\x" + ("0" + cp.toString(16)).slice(-2)); + } + } + }, { + key: "collectControlChars", + value: function collectControlChars(regexpStr) { + try { + this._source = regexpStr; + this._validator.validatePattern(regexpStr); // Call onCharacter hook + } catch (err) { + + // Ignore syntax errors in RegExp. + } + return this._controlChars; + } + }]); + + return _class; +}())(); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ module.exports = { meta: { + type: "problem", + docs: { description: "disallow control characters in regular expressions", category: "Possible Errors", @@ -73244,81 +80863,23 @@ module.exports = { * @returns {RegExp|null} Regex if found else null * @private */ - function getRegExp(node) { - if (node.value instanceof RegExp) { - return node.value; + function getRegExpPattern(node) { + if (node.regex) { + return node.regex.pattern; } - if (typeof node.value === "string") { - - var parent = context.getAncestors().pop(); - - if ((parent.type === "NewExpression" || parent.type === "CallExpression") && parent.callee.type === "Identifier" && parent.callee.name === "RegExp") { - - // there could be an invalid regular expression string - try { - return new RegExp(node.value); - } catch (ex) { - return null; - } - } + if (typeof node.value === "string" && (node.parent.type === "NewExpression" || node.parent.type === "CallExpression") && node.parent.callee.type === "Identifier" && node.parent.callee.name === "RegExp" && node.parent.arguments[0] === node) { + return node.value; } return null; } - var controlChar = /[\x00-\x1f]/g; // eslint-disable-line no-control-regex - var consecutiveSlashes = /\\+/g; - var consecutiveSlashesAtEnd = /\\+$/g; - var stringControlChar = /\\x[01][0-9a-f]/ig; - var stringControlCharWithoutSlash = /x[01][0-9a-f]/ig; - - /** - * Return a list of the control characters in the given regex string - * @param {string} regexStr regex as string to check - * @returns {array} returns a list of found control characters on given string - * @private - */ - function getControlCharacters(regexStr) { - - // check control characters, if RegExp object used - var controlChars = regexStr.match(controlChar) || []; - - var stringControlChars = []; - - // check substr, if regex literal used - var subStrIndex = regexStr.search(stringControlChar); - - if (subStrIndex > -1) { - - // is it escaped, check backslash count - var possibleEscapeCharacters = regexStr.slice(0, subStrIndex).match(consecutiveSlashesAtEnd); - - var hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2); - - if (hasControlChars) { - stringControlChars = regexStr.slice(subStrIndex, -1).split(consecutiveSlashes).filter(Boolean).map(function (x) { - var match = x.match(stringControlCharWithoutSlash) || [x]; - - return "\\" + match[0]; - }); - } - } - - return controlChars.map(function (x) { - var hexCode = ("0" + x.charCodeAt(0).toString(16)).slice(-2); - - return "\\x" + hexCode; - }).concat(stringControlChars); - } - return { Literal: function Literal(node) { - var regex = getRegExp(node); + var pattern = getRegExpPattern(node); - if (regex) { - var computedValue = regex.toString(); - - var controlCharacters = getControlCharacters(computedValue); + if (pattern) { + var controlCharacters = collector.collectControlChars(pattern); if (controlCharacters.length > 0) { context.report({ @@ -73335,7 +80896,7 @@ module.exports = { } }; -},{}],216:[function(require,module,exports){ +},{"regexpp":104}],214:[function(require,module,exports){ /** * @fileoverview Rule to flag use of a debugger statement * @author Nicholas C. Zakas @@ -73343,22 +80904,24 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); - //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ module.exports = { meta: { + type: "problem", + docs: { description: "disallow the use of `debugger`", category: "Possible Errors", recommended: true, url: "https://eslint.org/docs/rules/no-debugger" }, - fixable: "code", + + fixable: null, schema: [], + messages: { unexpected: "Unexpected 'debugger' statement." } @@ -73370,20 +80933,14 @@ module.exports = { DebuggerStatement: function DebuggerStatement(node) { context.report({ node: node, - messageId: "unexpected", - fix: function fix(fixer) { - if (astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) { - return fixer.remove(node); - } - return null; - } + messageId: "unexpected" }); } }; } }; -},{"../ast-utils":115}],217:[function(require,module,exports){ +},{}],215:[function(require,module,exports){ /** * @fileoverview Rule to flag when deleting variables * @author Ilya Volodin @@ -73397,6 +80954,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow deleting variables", category: "Variables", @@ -73423,7 +80982,7 @@ module.exports = { } }; -},{}],218:[function(require,module,exports){ +},{}],216:[function(require,module,exports){ /** * @fileoverview Rule to check for ambiguous div operator in regexes * @author Matt DuVall @@ -73437,6 +80996,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow division operators explicitly at the beginning of regular expressions", category: "Best Practices", @@ -73466,7 +81027,7 @@ module.exports = { } }; -},{}],219:[function(require,module,exports){ +},{}],217:[function(require,module,exports){ /** * @fileoverview Rule to flag duplicate arguments * @author Jamund Ferguson @@ -73480,6 +81041,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow duplicate arguments in `function` definitions", category: "Possible Errors", @@ -73545,7 +81108,7 @@ module.exports = { } }; -},{}],220:[function(require,module,exports){ +},{}],218:[function(require,module,exports){ /** * @fileoverview A rule to disallow duplicate name in class members. * @author Toru Nagashima @@ -73559,6 +81122,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow duplicate class members", category: "ECMAScript 6", @@ -73667,7 +81232,7 @@ module.exports = { } }; -},{}],221:[function(require,module,exports){ +},{}],219:[function(require,module,exports){ /** * @fileoverview Rule to flag use of duplicate keys in an object. * @author Ian Christian Myers @@ -73683,7 +81248,7 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -73771,6 +81336,8 @@ var ObjectInfo = function () { module.exports = { meta: { + type: "problem", + docs: { description: "disallow duplicate keys in object literals", category: "Possible Errors", @@ -73825,7 +81392,7 @@ module.exports = { } }; -},{"../ast-utils":115}],222:[function(require,module,exports){ +},{"../util/ast-utils":405}],220:[function(require,module,exports){ /** * @fileoverview Rule to disallow a duplicate case label. * @author Dieter Oberkofler @@ -73840,6 +81407,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow duplicate case labels", category: "Possible Errors", @@ -73875,7 +81444,7 @@ module.exports = { } }; -},{}],223:[function(require,module,exports){ +},{}],221:[function(require,module,exports){ /** * @fileoverview Restrict usage of duplicate imports. * @author Simen Bekkhus @@ -73980,6 +81549,8 @@ function handleExports(context, importsInFile, exportsInFile) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow duplicate module imports", category: "ECMAScript 6", @@ -74016,7 +81587,7 @@ module.exports = { } }; -},{}],224:[function(require,module,exports){ +},{}],222:[function(require,module,exports){ /** * @fileoverview Rule to flag `else` after a `return` in `if` * @author Ian Christian Myers @@ -74028,7 +81599,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var FixTracker = require("../util/fix-tracker"); //------------------------------------------------------------------------------ @@ -74037,6 +81608,8 @@ var FixTracker = require("../util/fix-tracker"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `else` blocks after `return` statements in `if` statements", category: "Best Practices", @@ -74198,7 +81771,6 @@ module.exports = { * code paths. * * @param {Node} node The consequent or body node - * @param {Node} alternate The alternate node * @returns {boolean} `true` if it is a Return/If node that always returns. */ function checkForReturnOrIf(node) { @@ -74232,8 +81804,6 @@ module.exports = { */ function checkIfWithoutElse(node) { var parent = node.parent; - var consequents = void 0, - alternate = void 0; /* * Fixing this would require splitting one statement into two, so no error should @@ -74243,12 +81813,15 @@ module.exports = { return; } - for (consequents = []; node.type === "IfStatement"; node = node.alternate) { - if (!node.alternate) { + var consequents = []; + var alternate = void 0; + + for (var currentNode = node; currentNode.type === "IfStatement"; currentNode = currentNode.alternate) { + if (!currentNode.alternate) { return; } - consequents.push(node.consequent); - alternate = node.alternate; + consequents.push(currentNode.consequent); + alternate = currentNode.alternate; } if (consequents.every(alwaysReturns)) { @@ -74294,7 +81867,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/fix-tracker":403}],225:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/fix-tracker":407}],223:[function(require,module,exports){ /** * @fileoverview Rule to flag the use of empty character classes in regular expressions * @author Ian Christian Myers @@ -74319,7 +81892,7 @@ module.exports = { * 5. `$`: fix the match at the end of the string */ -var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuy]*$/; +var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuys]*$/; //------------------------------------------------------------------------------ // Rule Definition @@ -74327,6 +81900,8 @@ var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+])*\/[gimuy]*$/; module.exports = { meta: { + type: "problem", + docs: { description: "disallow empty character classes in regular expressions", category: "Possible Errors", @@ -74356,7 +81931,7 @@ module.exports = { } }; -},{}],226:[function(require,module,exports){ +},{}],224:[function(require,module,exports){ /** * @fileoverview Rule to disallow empty functions. * @author Toru Nagashima @@ -74368,7 +81943,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -74438,6 +82013,8 @@ function getKind(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow empty functions", category: "Best Practices", @@ -74506,7 +82083,7 @@ module.exports = { } }; -},{"../ast-utils":115}],227:[function(require,module,exports){ +},{"../util/ast-utils":405}],225:[function(require,module,exports){ /** * @fileoverview Rule to disallow an empty pattern * @author Alberto Rodríguez @@ -74519,6 +82096,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow empty destructuring patterns", category: "Best Practices", @@ -74549,7 +82128,7 @@ module.exports = { } }; -},{}],228:[function(require,module,exports){ +},{}],226:[function(require,module,exports){ /** * @fileoverview Rule to flag use of an empty block statement * @author Nicholas C. Zakas @@ -74560,7 +82139,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -74568,6 +82147,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow empty block statements", category: "Possible Errors", @@ -74630,7 +82211,7 @@ module.exports = { } }; -},{"../ast-utils":115}],229:[function(require,module,exports){ +},{"../util/ast-utils":405}],227:[function(require,module,exports){ /** * @fileoverview Rule to flag comparisons to null without a type-checking * operator. @@ -74645,6 +82226,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `null` comparisons without type-checking operators", category: "Best Practices", @@ -74673,7 +82256,7 @@ module.exports = { } }; -},{}],230:[function(require,module,exports){ +},{}],228:[function(require,module,exports){ /** * @fileoverview Rule to flag use of eval() statement * @author Nicholas C. Zakas @@ -74685,7 +82268,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -74743,6 +82326,8 @@ function isMember(node, name) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `eval()`", category: "Best Practices", @@ -74813,18 +82398,13 @@ module.exports = { * @returns {void} */ function report(node) { - var locationNode = node; var parent = node.parent; + var locationNode = node.type === "MemberExpression" ? node.property : node; - if (node.type === "MemberExpression") { - locationNode = node.property; - } - if (parent.type === "CallExpression" && parent.callee === node) { - node = parent; - } + var reportNode = parent.type === "CallExpression" && parent.callee === node ? parent : node; context.report({ - node: node, + node: reportNode, loc: locationNode.loc.start, messageId: "unexpected" }); @@ -74966,7 +82546,7 @@ module.exports = { } }; -},{"../ast-utils":115}],231:[function(require,module,exports){ +},{"../util/ast-utils":405}],229:[function(require,module,exports){ /** * @fileoverview Rule to flag assignment of the exception parameter * @author Stephen Murray @@ -74974,7 +82554,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -74982,6 +82562,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow reassigning exceptions in `catch` clauses", category: "Possible Errors", @@ -75017,7 +82599,7 @@ module.exports = { } }; -},{"../ast-utils":115}],232:[function(require,module,exports){ +},{"../util/ast-utils":405}],230:[function(require,module,exports){ /** * @fileoverview Rule to flag adding properties to native object's prototypes. * @author David Nelson @@ -75029,7 +82611,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var globals = require("globals"); //------------------------------------------------------------------------------ @@ -75044,6 +82626,8 @@ var propertyDefinitionMethods = new Set(["defineProperty", "defineProperties"]); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow extending native types", category: "Best Practices", @@ -75174,7 +82758,7 @@ module.exports = { } }; -},{"../ast-utils":115,"globals":83}],233:[function(require,module,exports){ +},{"../util/ast-utils":405,"globals":85}],231:[function(require,module,exports){ /** * @fileoverview Rule to flag unnecessary bind calls * @author Bence Dányi @@ -75185,7 +82769,13 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +var SIDE_EFFECT_FREE_NODE_TYPES = new Set(["Literal", "Identifier", "ThisExpression", "FunctionExpression"]); //------------------------------------------------------------------------------ // Rule Definition @@ -75193,6 +82783,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary calls to `.bind()`", category: "Best Practices", @@ -75201,7 +82793,6 @@ module.exports = { }, schema: [], - fixable: "code", messages: { @@ -75212,6 +82803,18 @@ module.exports = { create: function create(context) { var scopeInfo = null; + /** + * Checks if a node is free of side effects. + * + * This check is stricter than it needs to be, in order to keep the implementation simple. + * + * @param {ASTNode} node A node to check. + * @returns {boolean} True if the node is known to be side-effect free, false otherwise. + */ + function isSideEffectFree(node) { + return SIDE_EFFECT_FREE_NODE_TYPES.has(node.type); + } + /** * Reports a given function node. * @@ -75225,6 +82828,10 @@ module.exports = { messageId: "unexpected", loc: node.parent.property.loc.start, fix: function fix(fixer) { + if (node.parent.parent.arguments.length && !isSideEffectFree(node.parent.parent.arguments[0])) { + return null; + } + var firstTokenToRemove = context.getSourceCode().getFirstTokenBetween(node.parent.object, node.parent.property, astUtils.isNotClosingParenToken); return fixer.removeRange([firstTokenToRemove.range[0], node.parent.parent.range[1]]); @@ -75317,7 +82924,7 @@ module.exports = { } }; -},{"../ast-utils":115}],234:[function(require,module,exports){ +},{"../util/ast-utils":405}],232:[function(require,module,exports){ /** * @fileoverview Rule to flag unnecessary double negation in Boolean contexts * @author Brandon Mills @@ -75329,7 +82936,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -75337,6 +82944,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary boolean casts", category: "Possible Errors", @@ -75345,7 +82954,6 @@ module.exports = { }, schema: [], - fixable: "code", messages: { @@ -75432,7 +83040,7 @@ module.exports = { } }; -},{"../ast-utils":115}],235:[function(require,module,exports){ +},{"../util/ast-utils":405}],233:[function(require,module,exports){ /** * @fileoverview Rule to disallow unnecessary labels * @author Toru Nagashima @@ -75444,7 +83052,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -75452,6 +83060,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary labels", category: "Best Practices", @@ -75460,7 +83070,6 @@ module.exports = { }, schema: [], - fixable: "code", messages: { @@ -75581,7 +83190,7 @@ module.exports = { } }; -},{"../ast-utils":115}],236:[function(require,module,exports){ +},{"../util/ast-utils":405}],234:[function(require,module,exports){ /** * @fileoverview Disallow parenthesising higher precedence subexpressions. * @author Michael Ficarra @@ -75592,10 +83201,12 @@ module.exports = { // Rule Definition //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils.js"); +var astUtils = require("../util/ast-utils.js"); module.exports = { meta: { + type: "layout", + docs: { description: "disallow unnecessary parentheses", category: "Possible Errors", @@ -75634,7 +83245,7 @@ module.exports = { }, messages: { - unexpected: "Gratuitous parentheses around expression." + unexpected: "Unnecessary parentheses around expression." } }, @@ -75661,7 +83272,7 @@ module.exports = { * @private */ function ruleApplies(node) { - if (node.type === "JSXElement") { + if (node.type === "JSXElement" || node.type === "JSXFragment") { var isSingleLine = node.loc.start.line === node.loc.end.line; switch (IGNORE_JSX) { @@ -75740,11 +83351,10 @@ module.exports = { * @private */ function isInReturnStatement(node) { - while (node) { - if (node.type === "ReturnStatement" || node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") { + for (var currentNode = node; currentNode; currentNode = currentNode.parent) { + if (currentNode.type === "ReturnStatement" || currentNode.type === "ArrowFunctionExpression" && currentNode.body.type !== "BlockStatement") { return true; } - node = node.parent; } return false; @@ -76112,12 +83722,10 @@ module.exports = { * If `let` is the only thing on the left side of the loop, it's the loop variable: `for ((let) of foo);` * Removing it will cause a syntax error, because it will be parsed as the start of a VariableDeclarator. */ - firstLeftToken.range[1] === node.left.range[1] || - - /* - * If `let` is followed by a `[` token, it's a property access on the `let` value: `for ((let[foo]) of bar);` - * Removing it will cause the property access to be parsed as a destructuring declaration of `foo` instead. - */ + firstLeftToken.range[1] === node.left.range[1] || /* + * If `let` is followed by a `[` token, it's a property access on the `let` value: `for ((let[foo]) of bar);` + * Removing it will cause the property access to be parsed as a destructuring declaration of `foo` instead. + */ astUtils.isOpeningBracketToken(sourceCode.getTokenAfter(firstLeftToken, astUtils.isNotClosingParenToken)))) { tokensToIgnore.add(firstLeftToken); } @@ -76263,7 +83871,7 @@ module.exports = { } }; -},{"../ast-utils.js":115}],237:[function(require,module,exports){ +},{"../util/ast-utils.js":405}],235:[function(require,module,exports){ /** * @fileoverview Rule to flag use of unnecessary semicolons * @author Nicholas C. Zakas @@ -76276,7 +83884,7 @@ module.exports = { //------------------------------------------------------------------------------ var FixTracker = require("../util/fix-tracker"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -76284,6 +83892,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary semicolons", category: "Possible Errors", @@ -76377,7 +83987,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/fix-tracker":403}],238:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/fix-tracker":407}],236:[function(require,module,exports){ /** * @fileoverview Rule to flag fall-through cases in switch statements. * @author Matt DuVall @@ -76435,6 +84045,8 @@ function hasBlankLinesBetween(node, token) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow fallthrough of `case` statements", category: "Best Practices", @@ -76509,7 +84121,7 @@ module.exports = { } }; -},{"lodash":89}],239:[function(require,module,exports){ +},{"lodash":92}],237:[function(require,module,exports){ /** * @fileoverview Rule to flag use of a leading/trailing decimal point in a numeric literal * @author James Allardice @@ -76521,7 +84133,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -76529,6 +84141,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow leading or trailing decimal points in numeric literals", category: "Best Practices", @@ -76537,7 +84151,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -76575,7 +84188,7 @@ module.exports = { } }; -},{"../ast-utils":115}],240:[function(require,module,exports){ +},{"../util/ast-utils":405}],238:[function(require,module,exports){ /** * @fileoverview Rule to flag use of function declaration identifiers as variables. * @author Ian Christian Myers @@ -76583,7 +84196,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -76591,6 +84204,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow reassigning `function` declarations", category: "Possible Errors", @@ -76641,7 +84256,7 @@ module.exports = { } }; -},{"../ast-utils":115}],241:[function(require,module,exports){ +},{"../util/ast-utils":405}],239:[function(require,module,exports){ /** * @fileoverview Rule to disallow assignments to native objects or read-only global variables * @author Ilya Volodin @@ -76655,6 +84270,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow assignments to native objects or read-only global variables", category: "Best Practices", @@ -76725,7 +84342,7 @@ module.exports = { } }; -},{}],242:[function(require,module,exports){ +},{}],240:[function(require,module,exports){ /** * @fileoverview A rule to disallow the type conversions with shorter notations. * @author Toru Nagashima @@ -76733,7 +84350,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -76748,7 +84365,6 @@ var ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; * @returns {Object} The parsed and normalized option object. */ function parseOptions(options) { - options = options || {}; return { boolean: "boolean" in options ? Boolean(options.boolean) : true, number: "number" in options ? Boolean(options.number) : true, @@ -76858,6 +84474,8 @@ function getNonEmptyOperand(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow shorthand type conversions", category: "Best Practices", @@ -76866,6 +84484,7 @@ module.exports = { }, fixable: "code", + schema: [{ type: "object", properties: { @@ -76891,7 +84510,7 @@ module.exports = { }, create: function create(context) { - var options = parseOptions(context.options[0]); + var options = parseOptions(context.options[0] || {}); var sourceCode = context.getSourceCode(); /** @@ -76902,8 +84521,6 @@ module.exports = { * @returns {void} */ function report(node, recommendation, shouldFix) { - shouldFix = typeof shouldFix === "undefined" ? true : shouldFix; - context.report({ node: node, message: "use `{{recommendation}}` instead.", @@ -76934,7 +84551,7 @@ module.exports = { if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) { var recommendation = "Boolean(" + sourceCode.getText(node.argument.argument) + ")"; - report(node, recommendation); + report(node, recommendation, true); } // ~foo.indexOf(bar) @@ -76950,7 +84567,7 @@ module.exports = { if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) { var _recommendation2 = "Number(" + sourceCode.getText(node.argument) + ")"; - report(node, _recommendation2); + report(node, _recommendation2, true); } }, @@ -76966,7 +84583,7 @@ module.exports = { if (nonNumericOperand) { var recommendation = "Number(" + sourceCode.getText(nonNumericOperand) + ")"; - report(node, recommendation); + report(node, recommendation, true); } // "" + foo @@ -76974,7 +84591,7 @@ module.exports = { if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) { var _recommendation3 = "String(" + sourceCode.getText(getNonEmptyOperand(node)) + ")"; - report(node, _recommendation3); + report(node, _recommendation3, true); } }, AssignmentExpression: function AssignmentExpression(node) { @@ -76986,14 +84603,14 @@ module.exports = { var code = sourceCode.getText(getNonEmptyOperand(node)); var recommendation = code + " = String(" + code + ")"; - report(node, recommendation); + report(node, recommendation, true); } } }; } }; -},{"../ast-utils":115}],243:[function(require,module,exports){ +},{"../util/ast-utils":405}],241:[function(require,module,exports){ /** * @fileoverview Rule to check for implicit global variables and functions. * @author Joshua Peek @@ -77007,6 +84624,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow variable and `function` declarations in the global scope", category: "Best Practices", @@ -77050,7 +84669,7 @@ module.exports = { } }; -},{}],244:[function(require,module,exports){ +},{}],242:[function(require,module,exports){ /** * @fileoverview Rule to flag use of implied eval via setTimeout and setInterval * @author James Allardice @@ -77064,6 +84683,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `eval()`-like methods", category: "Best Practices", @@ -77089,7 +84710,7 @@ module.exports = { /** * Get the last element of an array, without modifying arr, like pop(), but non-destructive. - * @param {array} arr What to inspect + * @param {Array} arr What to inspect * @returns {*} The last element of arr * @private */ @@ -77206,14 +84827,14 @@ module.exports = { } }; -},{}],245:[function(require,module,exports){ +},{}],243:[function(require,module,exports){ /** * @fileoverview Enforces or disallows inline comments. * @author Greg Cochard */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -77221,6 +84842,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow inline comments after code", category: "Stylistic Issues", @@ -77276,7 +84899,7 @@ module.exports = { } }; -},{"../ast-utils":115}],246:[function(require,module,exports){ +},{"../util/ast-utils":405}],244:[function(require,module,exports){ /** * @fileoverview Rule to enforce declarations in program or function body root. * @author Brandon Mills @@ -77290,6 +84913,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow variable or `function` declarations in nested blocks", category: "Possible Errors", @@ -77361,7 +84986,7 @@ module.exports = { } }; -},{}],247:[function(require,module,exports){ +},{}],245:[function(require,module,exports){ /** * @fileoverview Validate strings passed to the RegExp constructor * @author Michael Ficarra @@ -77372,7 +84997,10 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var espree = require("espree"); +var RegExpValidator = require("regexpp").RegExpValidator; +var validator = new RegExpValidator({ ecmaVersion: 2018 }); +var validFlags = /[gimuys]/g; +var undefined1 = void 0; //------------------------------------------------------------------------------ // Rule Definition @@ -77380,6 +85008,8 @@ var espree = require("espree"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow invalid regular expression strings in `RegExp` constructors", category: "Possible Errors", @@ -77404,10 +85034,14 @@ module.exports = { create: function create(context) { var options = context.options[0]; - var allowedFlags = ""; + var allowedFlags = null; if (options && options.allowConstructorFlags) { - allowedFlags = options.allowConstructorFlags.join(""); + var temp = options.allowConstructorFlags.join("").replace(validFlags, ""); + + if (temp) { + allowedFlags = new RegExp("[" + temp + "]", "gi"); + } } /** @@ -77421,54 +85055,62 @@ module.exports = { } /** - * Validate strings passed to the RegExp constructor - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private + * Check syntax error in a given pattern. + * @param {string} pattern The RegExp pattern to validate. + * @param {boolean} uFlag The Unicode flag. + * @returns {string|null} The syntax error. */ - function check(node) { - if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) { - var flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; + function validateRegExpPattern(pattern, uFlag) { + try { + validator.validatePattern(pattern, undefined1, undefined1, uFlag); + return null; + } catch (err) { + return err.message; + } + } - if (allowedFlags) { - flags = flags.replace(new RegExp("[" + allowedFlags + "]", "gi"), ""); - } - - try { - void new RegExp(node.arguments[0].value); - } catch (e) { - context.report({ - node: node, - message: "{{message}}.", - data: e - }); - } - - if (flags) { - - try { - espree.parse("/./" + flags, context.parserOptions); - } catch (ex) { - context.report({ - node: node, - message: "Invalid flags supplied to RegExp constructor '{{flags}}'.", - data: { - flags: flags - } - }); - } - } + /** + * Check syntax error in a given flags. + * @param {string} flags The RegExp flags to validate. + * @returns {string|null} The syntax error. + */ + function validateRegExpFlags(flags) { + try { + validator.validateFlags(flags); + return null; + } catch (err) { + return "Invalid flags supplied to RegExp constructor '" + flags + "'"; } } return { - CallExpression: check, - NewExpression: check + "CallExpression, NewExpression": function CallExpressionNewExpression(node) { + if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) { + return; + } + var pattern = node.arguments[0].value; + var flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; + + if (allowedFlags) { + flags = flags.replace(allowedFlags, ""); + } + + // If flags are unknown, check both are errored or not. + var message = validateRegExpFlags(flags) || (flags ? validateRegExpPattern(pattern, flags.indexOf("u") !== -1) : validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)); + + if (message) { + context.report({ + node: node, + message: "{{message}}.", + data: { message: message } + }); + } + } }; } }; -},{"espree":"espree"}],248:[function(require,module,exports){ +},{"regexpp":104}],246:[function(require,module,exports){ /** * @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects. * @author Toru Nagashima @@ -77480,7 +85122,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -77488,6 +85130,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `this` keywords outside of classes or class-like objects", category: "Best Practices", @@ -77587,7 +85231,7 @@ module.exports = { } }; -},{"../ast-utils":115}],249:[function(require,module,exports){ +},{"../util/ast-utils":405}],247:[function(require,module,exports){ /** * @fileoverview Rule to disalow whitespace that is not a tab or space, whitespace inside strings and comments are allowed * @author Jonathan Kingston @@ -77600,7 +85244,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Constants @@ -77617,8 +85261,10 @@ var LINE_BREAK = astUtils.createGlobalLinebreakMatcher(); module.exports = { meta: { + type: "problem", + docs: { - description: "disallow irregular whitespace outside of strings and comments", + description: "disallow irregular whitespace", category: "Possible Errors", recommended: true, url: "https://eslint.org/docs/rules/no-irregular-whitespace" @@ -77669,8 +85315,8 @@ module.exports = { var locStart = node.loc.start; var locEnd = node.loc.end; - errors = errors.filter(function (error) { - var errorLoc = error[1]; + errors = errors.filter(function (_ref) { + var errorLoc = _ref.loc; if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) { if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) { @@ -77689,7 +85335,7 @@ module.exports = { */ function removeInvalidNodeErrorsInIdentifierOrLiteral(node) { var shouldCheckStrings = skipStrings && typeof node.value === "string"; - var shouldCheckRegExps = skipRegExps && node.value instanceof RegExp; + var shouldCheckRegExps = skipRegExps && Boolean(node.regex); if (shouldCheckStrings || shouldCheckRegExps) { @@ -77745,7 +85391,7 @@ module.exports = { column: match.index }; - errors.push([node, location, "Irregular whitespace not allowed."]); + errors.push({ node: node, message: "Irregular whitespace not allowed.", loc: location }); } }); } @@ -77770,7 +85416,7 @@ module.exports = { column: sourceLines[lineIndex].length }; - errors.push([node, location, "Irregular whitespace not allowed."]); + errors.push({ node: node, message: "Irregular whitespace not allowed.", loc: location }); lastLineIndex = lineIndex; } } @@ -77813,7 +85459,7 @@ module.exports = { // If we have any errors remaining report on them errors.forEach(function (error) { - context.report.apply(context, error); + return context.report(error); }); }; } else { @@ -77824,7 +85470,7 @@ module.exports = { } }; -},{"../ast-utils":115}],250:[function(require,module,exports){ +},{"../util/ast-utils":405}],248:[function(require,module,exports){ /** * @fileoverview Rule to flag usage of __iterator__ property * @author Ian Christian Myers @@ -77838,6 +85484,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of the `__iterator__` property", category: "Best Practices", @@ -77861,7 +85509,7 @@ module.exports = { } }; -},{}],251:[function(require,module,exports){ +},{}],249:[function(require,module,exports){ /** * @fileoverview Rule to flag labels that are the same as an identifier * @author Ian Christian Myers @@ -77873,7 +85521,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -77881,6 +85529,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow labels that share a name with a variable", category: "Variables", @@ -77930,7 +85580,7 @@ module.exports = { } }; -},{"../ast-utils":115}],252:[function(require,module,exports){ +},{"../util/ast-utils":405}],250:[function(require,module,exports){ /** * @fileoverview Disallow Labeled Statements * @author Nicholas C. Zakas @@ -77941,7 +85591,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -77949,6 +85599,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow labeled statements", category: "Best Practices", @@ -78071,7 +85723,7 @@ module.exports = { } }; -},{"../ast-utils":115}],253:[function(require,module,exports){ +},{"../util/ast-utils":405}],251:[function(require,module,exports){ /** * @fileoverview Rule to flag blocks with no reason to exist * @author Brandon Mills @@ -78085,6 +85737,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary nested blocks", category: "Best Practices", @@ -78185,7 +85839,7 @@ module.exports = { } }; -},{}],254:[function(require,module,exports){ +},{}],252:[function(require,module,exports){ /** * @fileoverview Rule to disallow if as the only statmenet in an else block * @author Brandon Mills @@ -78198,6 +85852,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `if` statements as the only statement in `else` blocks", category: "Stylistic Issues", @@ -78206,7 +85862,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -78255,7 +85910,7 @@ module.exports = { } }; -},{}],255:[function(require,module,exports){ +},{}],253:[function(require,module,exports){ /** * @fileoverview Rule to flag creation of function inside a loop * @author Ilya Volodin @@ -78279,9 +85934,9 @@ module.exports = { */ function getContainingLoopNode(node) { - var parent = node.parent; + for (var currentNode = node; currentNode.parent; currentNode = currentNode.parent) { + var parent = currentNode.parent; - while (parent) { switch (parent.type) { case "WhileStatement": case "DoWhileStatement": @@ -78290,7 +85945,7 @@ function getContainingLoopNode(node) { case "ForStatement": // `init` is outside of the loop. - if (parent.init !== node) { + if (parent.init !== currentNode) { return parent; } break; @@ -78299,7 +85954,7 @@ function getContainingLoopNode(node) { case "ForOfStatement": // `right` is outside of the loop. - if (parent.right !== node) { + if (parent.right !== currentNode) { return parent; } break; @@ -78314,9 +85969,6 @@ function getContainingLoopNode(node) { default: break; } - - node = parent; - parent = node.parent; } return null; @@ -78332,12 +85984,13 @@ function getContainingLoopNode(node) { * @returns {ASTNode} The most outer loop node. */ function getTopLoopNode(node, excludedNode) { - var retv = node; var border = excludedNode ? excludedNode.range[1] : 0; + var retv = node; + var containingLoopNode = node; - while (node && node.range[0] >= border) { - retv = node; - node = getContainingLoopNode(node); + while (containingLoopNode && containingLoopNode.range[0] >= border) { + retv = containingLoopNode; + containingLoopNode = getContainingLoopNode(containingLoopNode); } return retv; @@ -78403,6 +86056,8 @@ function isSafe(loopNode, reference) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `function` declarations and expressions inside loop statements", category: "Best Practices", @@ -78446,7 +86101,7 @@ module.exports = { } }; -},{}],256:[function(require,module,exports){ +},{}],254:[function(require,module,exports){ /** * @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js) * @author Vincent Lemeunier @@ -78460,6 +86115,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow magic numbers", category: "Best Practices", @@ -78488,7 +86145,12 @@ module.exports = { } }, additionalProperties: false - }] + }], + + messages: { + useConst: "Number constants declarations must use 'const'.", + noMagic: "No magic number: {{raw}}." + } }, create: function create(context) { @@ -78546,38 +86208,45 @@ module.exports = { return { Literal: function Literal(node) { - var parent = node.parent, - value = node.value, - raw = node.raw; var okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; if (!isNumber(node)) { return; } + var fullNumberNode = void 0; + var parent = void 0; + var value = void 0; + var raw = void 0; + // For negative magic numbers: update the value and parent node - if (parent.type === "UnaryExpression" && parent.operator === "-") { - node = parent; + if (node.parent.type === "UnaryExpression" && node.parent.operator === "-") { + fullNumberNode = node.parent; + parent = fullNumberNode.parent; + value = -node.value; + raw = "-" + node.raw; + } else { + fullNumberNode = node; parent = node.parent; - value = -value; - raw = "-" + raw; + value = node.value; + raw = node.raw; } - if (shouldIgnoreNumber(value) || shouldIgnoreParseInt(parent, node) || shouldIgnoreArrayIndexes(parent) || shouldIgnoreJSXNumbers(parent)) { + if (shouldIgnoreNumber(value) || shouldIgnoreParseInt(parent, fullNumberNode) || shouldIgnoreArrayIndexes(parent) || shouldIgnoreJSXNumbers(parent)) { return; } if (parent.type === "VariableDeclarator") { if (enforceConst && parent.parent.kind !== "const") { context.report({ - node: node, - message: "Number constants declarations must use 'const'." + node: fullNumberNode, + messageId: "useConst" }); } } else if (okTypes.indexOf(parent.type) === -1 || parent.type === "AssignmentExpression" && parent.left.type === "Identifier") { context.report({ - node: node, - message: "No magic number: {{raw}}.", + node: fullNumberNode, + messageId: "noMagic", data: { raw: raw } @@ -78588,7 +86257,371 @@ module.exports = { } }; -},{}],257:[function(require,module,exports){ +},{}],255:[function(require,module,exports){ +/** + * @author Toru Nagashima + */ +"use strict"; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var _marked = /*#__PURE__*/regeneratorRuntime.mark(iterateCharacterSequence); + +var _require = require("eslint-utils"), + CALL = _require.CALL, + CONSTRUCT = _require.CONSTRUCT, + ReferenceTracker = _require.ReferenceTracker, + getStringIfConstant = _require.getStringIfConstant; + +var _require2 = require("regexpp"), + RegExpParser = _require2.RegExpParser, + visitRegExpAST = _require2.visitRegExpAST; + +var _require3 = require("../util/unicode"), + isCombiningCharacter = _require3.isCombiningCharacter, + isEmojiModifier = _require3.isEmojiModifier, + isRegionalIndicatorSymbol = _require3.isRegionalIndicatorSymbol, + isSurrogatePair = _require3.isSurrogatePair; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Iterate character sequences of a given nodes. + * + * CharacterClassRange syntax can steal a part of character sequence, + * so this function reverts CharacterClassRange syntax and restore the sequence. + * + * @param {regexpp.AST.CharacterClassElement[]} nodes The node list to iterate character sequences. + * @returns {IterableIterator} The list of character sequences. + */ + + +function iterateCharacterSequence(nodes) { + var seq, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, node; + + return regeneratorRuntime.wrap(function iterateCharacterSequence$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + seq = []; + _iteratorNormalCompletion = true; + _didIteratorError = false; + _iteratorError = undefined; + _context.prev = 4; + _iterator = nodes[Symbol.iterator](); + + case 6: + if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { + _context.next = 26; + break; + } + + node = _step.value; + _context.t0 = node.type; + _context.next = _context.t0 === "Character" ? 11 : _context.t0 === "CharacterClassRange" ? 13 : _context.t0 === "CharacterSet" ? 18 : 23; + break; + + case 11: + seq.push(node.value); + return _context.abrupt("break", 23); + + case 13: + seq.push(node.min.value); + _context.next = 16; + return seq; + + case 16: + seq = [node.max.value]; + return _context.abrupt("break", 23); + + case 18: + if (!(seq.length > 0)) { + _context.next = 22; + break; + } + + _context.next = 21; + return seq; + + case 21: + seq = []; + + case 22: + return _context.abrupt("break", 23); + + case 23: + _iteratorNormalCompletion = true; + _context.next = 6; + break; + + case 26: + _context.next = 32; + break; + + case 28: + _context.prev = 28; + _context.t1 = _context["catch"](4); + _didIteratorError = true; + _iteratorError = _context.t1; + + case 32: + _context.prev = 32; + _context.prev = 33; + + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + + case 35: + _context.prev = 35; + + if (!_didIteratorError) { + _context.next = 38; + break; + } + + throw _iteratorError; + + case 38: + return _context.finish(35); + + case 39: + return _context.finish(32); + + case 40: + if (!(seq.length > 0)) { + _context.next = 43; + break; + } + + _context.next = 43; + return seq; + + case 43: + case "end": + return _context.stop(); + } + } + }, _marked, this, [[4, 28, 32, 40], [33,, 35, 39]]); +} + +var hasCharacterSequence = { + surrogatePairWithoutUFlag: function surrogatePairWithoutUFlag(chars) { + return chars.some(function (c, i) { + return i !== 0 && isSurrogatePair(chars[i - 1], c); + }); + }, + combiningClass: function combiningClass(chars) { + return chars.some(function (c, i) { + return i !== 0 && isCombiningCharacter(c) && !isCombiningCharacter(chars[i - 1]); + }); + }, + emojiModifier: function emojiModifier(chars) { + return chars.some(function (c, i) { + return i !== 0 && isEmojiModifier(c) && !isEmojiModifier(chars[i - 1]); + }); + }, + regionalIndicatorSymbol: function regionalIndicatorSymbol(chars) { + return chars.some(function (c, i) { + return i !== 0 && isRegionalIndicatorSymbol(c) && isRegionalIndicatorSymbol(chars[i - 1]); + }); + }, + zwj: function zwj(chars) { + var lastIndex = chars.length - 1; + + return chars.some(function (c, i) { + return i !== 0 && i !== lastIndex && c === 0x200d && chars[i - 1] !== 0x200d && chars[i + 1] !== 0x200d; + }); + } +}; + +var kinds = Object.keys(hasCharacterSequence); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow characters which are made with multiple code points in character class syntax", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/no-misleading-character-class" + }, + + schema: [], + + messages: { + surrogatePairWithoutUFlag: "Unexpected surrogate pair in character class. Use 'u' flag.", + combiningClass: "Unexpected combined character in character class.", + emojiModifier: "Unexpected modified Emoji in character class.", + regionalIndicatorSymbol: "Unexpected national flag in character class.", + zwj: "Unexpected joined character sequence in character class." + } + }, + create: function create(context) { + var parser = new RegExpParser(); + + /** + * Verify a given regular expression. + * @param {Node} node The node to report. + * @param {string} pattern The regular expression pattern to verify. + * @param {string} flags The flags of the regular expression. + * @returns {void} + */ + function verify(node, pattern, flags) { + var patternNode = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); + var has = { + surrogatePairWithoutUFlag: false, + combiningClass: false, + variationSelector: false, + emojiModifier: false, + regionalIndicatorSymbol: false, + zwj: false + }; + + visitRegExpAST(patternNode, { + onCharacterClassEnter: function onCharacterClassEnter(ccNode) { + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = iterateCharacterSequence(ccNode.elements)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var chars = _step2.value; + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = kinds[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var kind = _step3.value; + + has[kind] = has[kind] || hasCharacterSequence[kind](chars); + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } + }); + + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for (var _iterator4 = kinds[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var kind = _step4.value; + + if (has[kind]) { + context.report({ node: node, messageId: kind }); + } + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if (!_iteratorNormalCompletion4 && _iterator4.return) { + _iterator4.return(); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + } + + return { + "Literal[regex]": function LiteralRegex(node) { + verify(node, node.regex.pattern, node.regex.flags); + }, + "Program": function Program() { + var scope = context.getScope(); + var tracker = new ReferenceTracker(scope); + + /* + * Iterate calls of RegExp. + * E.g., `new RegExp()`, `RegExp()`, `new window.RegExp()`, + * `const {RegExp: a} = window; new a()`, etc... + */ + var _iteratorNormalCompletion5 = true; + var _didIteratorError5 = false; + var _iteratorError5 = undefined; + + try { + for (var _iterator5 = tracker.iterateGlobalReferences({ + RegExp: (_RegExp = {}, _defineProperty(_RegExp, CALL, true), _defineProperty(_RegExp, CONSTRUCT, true), _RegExp) + })[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { + var _RegExp; + + var node = _step5.value.node; + + var _node$arguments = _slicedToArray(node.arguments, 2), + patternNode = _node$arguments[0], + flagsNode = _node$arguments[1]; + + var pattern = getStringIfConstant(patternNode, scope); + var flags = getStringIfConstant(flagsNode, scope); + + if (typeof pattern === "string") { + verify(node, pattern, flags || ""); + } + } + } catch (err) { + _didIteratorError5 = true; + _iteratorError5 = err; + } finally { + try { + if (!_iteratorNormalCompletion5 && _iterator5.return) { + _iterator5.return(); + } + } finally { + if (_didIteratorError5) { + throw _iteratorError5; + } + } + } + } + }; + } +}; + +},{"../util/unicode":419,"eslint-utils":68,"regexpp":104}],256:[function(require,module,exports){ /** * @fileoverview Rule to disallow mixed binary operators. * @author Toru Nagashima @@ -78600,7 +86633,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils.js"); +var astUtils = require("../util/ast-utils.js"); //------------------------------------------------------------------------------ // Helpers @@ -78652,12 +86685,15 @@ function includesBothInAGroup(groups, left, right) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow mixed binary operators", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/no-mixed-operators" }, + schema: [{ type: "object", properties: { @@ -78775,7 +86811,7 @@ module.exports = { } }; -},{"../ast-utils.js":115}],258:[function(require,module,exports){ +},{"../util/ast-utils.js":405}],257:[function(require,module,exports){ /** * @fileoverview Rule to enforce grouped require statements for Node.JS * @author Raphael Pigulla @@ -78791,6 +86827,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `require` calls to be mixed with regular variable declarations", category: "Node.js and CommonJS", @@ -78976,7 +87014,7 @@ module.exports = { } }; -},{}],259:[function(require,module,exports){ +},{}],258:[function(require,module,exports){ /** * @fileoverview Disallow mixed spaces and tabs for indentation * @author Jary Niebur @@ -78989,6 +87027,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "disallow mixed spaces and tabs for indentation", category: "Stylistic Issues", @@ -79116,7 +87156,7 @@ module.exports = { } }; -},{}],260:[function(require,module,exports){ +},{}],259:[function(require,module,exports){ /** * @fileoverview Rule to check use of chained assignment expressions * @author Stewart Rand @@ -79130,12 +87170,15 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow use of chained assignment expressions", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/no-multi-assign" }, + schema: [] }, @@ -79158,7 +87201,7 @@ module.exports = { } }; -},{}],261:[function(require,module,exports){ +},{}],260:[function(require,module,exports){ /** * @fileoverview Disallow use of multiple spaces. * @author Nicholas C. Zakas @@ -79166,7 +87209,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -79174,6 +87217,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "disallow multiple spaces", category: "Best Practices", @@ -79282,7 +87327,7 @@ module.exports = { } }; -},{"../ast-utils":115}],262:[function(require,module,exports){ +},{"../util/ast-utils":405}],261:[function(require,module,exports){ /** * @fileoverview Rule to flag when using multiline strings * @author Ilya Volodin @@ -79294,7 +87339,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -79302,6 +87347,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow multiline strings", category: "Best Practices", @@ -79338,7 +87385,7 @@ module.exports = { } }; -},{"../ast-utils":115}],263:[function(require,module,exports){ +},{"../util/ast-utils":405}],262:[function(require,module,exports){ /** * @fileoverview Disallows multiple blank lines. * implementation adapted from the no-trailing-spaces rule. @@ -79352,6 +87399,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "disallow multiple empty lines", category: "Stylistic Issues", @@ -79474,7 +87523,7 @@ module.exports = { } }; -},{}],264:[function(require,module,exports){ +},{}],263:[function(require,module,exports){ /** * @fileoverview Rule to disallow assignments to native objects or read-only global variables * @author Ilya Volodin @@ -79489,16 +87538,19 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow assignments to native objects or read-only global variables", category: "Best Practices", recommended: false, - replacedBy: ["no-global-assign"], url: "https://eslint.org/docs/rules/no-native-reassign" }, deprecated: true, + replacedBy: ["no-global-assign"], + schema: [{ type: "object", properties: { @@ -79562,7 +87614,7 @@ module.exports = { } }; -},{}],265:[function(require,module,exports){ +},{}],264:[function(require,module,exports){ /** * @fileoverview Rule to disallow a negated condition * @author Alberto Rodríguez @@ -79575,6 +87627,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow negated conditions", category: "Stylistic Issues", @@ -79646,7 +87700,7 @@ module.exports = { } }; -},{}],266:[function(require,module,exports){ +},{}],265:[function(require,module,exports){ /** * @fileoverview A rule to disallow negated left operands of the `in` operator * @author Michael Ficarra @@ -79661,15 +87715,18 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow negating the left operand in `in` expressions", category: "Possible Errors", recommended: false, - replacedBy: ["no-unsafe-negation"], url: "https://eslint.org/docs/rules/no-negated-in-lhs" }, - deprecated: true, + replacedBy: ["no-unsafe-negation"], + + deprecated: true, schema: [] }, @@ -79685,7 +87742,7 @@ module.exports = { } }; -},{}],267:[function(require,module,exports){ +},{}],266:[function(require,module,exports){ /** * @fileoverview Rule to flag nested ternary expressions * @author Ian Christian Myers @@ -79699,6 +87756,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow nested ternary expressions", category: "Stylistic Issues", @@ -79721,7 +87780,7 @@ module.exports = { } }; -},{}],268:[function(require,module,exports){ +},{}],267:[function(require,module,exports){ /** * @fileoverview Rule to flag when using new Function * @author Ilya Volodin @@ -79735,6 +87794,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `new` operators with the `Function` object", category: "Best Practices", @@ -79768,7 +87829,7 @@ module.exports = { } }; -},{}],269:[function(require,module,exports){ +},{}],268:[function(require,module,exports){ /** * @fileoverview A rule to disallow calls to the Object constructor * @author Matt DuVall @@ -79782,6 +87843,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `Object` constructors", category: "Stylistic Issues", @@ -79804,7 +87867,7 @@ module.exports = { } }; -},{}],270:[function(require,module,exports){ +},{}],269:[function(require,module,exports){ /** * @fileoverview Rule to disallow use of new operator with the `require` function * @author Wil Moore III @@ -79818,6 +87881,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `new` operators with calls to `require`", category: "Node.js and CommonJS", @@ -79840,7 +87905,7 @@ module.exports = { } }; -},{}],271:[function(require,module,exports){ +},{}],270:[function(require,module,exports){ /** * @fileoverview Rule to disallow use of the new operator with the `Symbol` object * @author Alberto Rodríguez @@ -79854,6 +87919,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow `new` operators with the `Symbol` object", category: "ECMAScript 6", @@ -79885,7 +87952,7 @@ module.exports = { } }; -},{}],272:[function(require,module,exports){ +},{}],271:[function(require,module,exports){ /** * @fileoverview Rule to flag when using constructor for wrapper objects * @author Ilya Volodin @@ -79899,6 +87966,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `new` operators with the `String`, `Number`, and `Boolean` objects", category: "Best Practices", @@ -79923,7 +87992,7 @@ module.exports = { } }; -},{}],273:[function(require,module,exports){ +},{}],272:[function(require,module,exports){ /** * @fileoverview Rule to flag statements with function invocation preceded by * "new" and not part of assignment @@ -79938,6 +88007,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `new` operators outside of assignments or comparisons", category: "Best Practices", @@ -79958,7 +88029,7 @@ module.exports = { } }; -},{}],274:[function(require,module,exports){ +},{}],273:[function(require,module,exports){ /** * @fileoverview Rule to flag use of an object property of the global object (Math and JSON) as a function * @author James Allardice @@ -79972,6 +88043,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow calling global object properties as functions", category: "Possible Errors", @@ -79999,7 +88072,7 @@ module.exports = { } }; -},{}],275:[function(require,module,exports){ +},{}],274:[function(require,module,exports){ /** * @fileoverview Rule to flag octal escape sequences in string literals. * @author Ian Christian Myers @@ -80013,6 +88086,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow octal escape sequences in string literals", category: "Best Practices", @@ -80046,7 +88121,7 @@ module.exports = { } }; -},{}],276:[function(require,module,exports){ +},{}],275:[function(require,module,exports){ /** * @fileoverview Rule to flag when initializing octal literal * @author Ilya Volodin @@ -80060,6 +88135,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow octal literals", category: "Best Practices", @@ -80082,7 +88159,7 @@ module.exports = { } }; -},{}],277:[function(require,module,exports){ +},{}],276:[function(require,module,exports){ /** * @fileoverview Disallow reassignment of function parameters. * @author Nat Burns @@ -80097,6 +88174,8 @@ var stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program) module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow reassigning `function` parameters", category: "Best Practices", @@ -80250,7 +88329,7 @@ module.exports = { } }; -},{}],278:[function(require,module,exports){ +},{}],277:[function(require,module,exports){ /** * @fileoverview Disallow string concatenation when using __dirname and __filename * @author Nicholas C. Zakas @@ -80263,6 +88342,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow string concatenation with `__dirname` and `__filename`", category: "Node.js and CommonJS", @@ -80296,7 +88377,7 @@ module.exports = { } }; -},{}],279:[function(require,module,exports){ +},{}],278:[function(require,module,exports){ /** * @fileoverview Rule to flag use of unary increment and decrement operators. * @author Ian Christian Myers @@ -80313,6 +88394,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the unary operators `++` and `--`", category: "Stylistic Issues", @@ -80357,7 +88440,7 @@ module.exports = { } }; -},{}],280:[function(require,module,exports){ +},{}],279:[function(require,module,exports){ /** * @fileoverview Disallow the use of process.env() * @author Vignesh Anand @@ -80370,6 +88453,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `process.env`", category: "Node.js and CommonJS", @@ -80395,7 +88480,7 @@ module.exports = { } }; -},{}],281:[function(require,module,exports){ +},{}],280:[function(require,module,exports){ /** * @fileoverview Disallow the use of process.exit() * @author Nicholas C. Zakas @@ -80408,6 +88493,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `process.exit()`", category: "Node.js and CommonJS", @@ -80432,7 +88519,7 @@ module.exports = { } }; -},{}],282:[function(require,module,exports){ +},{}],281:[function(require,module,exports){ /** * @fileoverview Rule to flag usage of __proto__ property * @author Ilya Volodin @@ -80446,6 +88533,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of the `__proto__` property", category: "Best Practices", @@ -80469,7 +88558,7 @@ module.exports = { } }; -},{}],283:[function(require,module,exports){ +},{}],282:[function(require,module,exports){ /** * @fileoverview Rule to disallow use of Object.prototype builtins on objects * @author Andrew Levine @@ -80482,6 +88571,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow calling some `Object.prototype` methods directly on objects", category: "Possible Errors", @@ -80522,7 +88613,7 @@ module.exports = { } }; -},{}],284:[function(require,module,exports){ +},{}],283:[function(require,module,exports){ /** * @fileoverview Rule to flag when the same variable is declared more then once. * @author Ilya Volodin @@ -80536,6 +88627,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow variable redeclaration", category: "Best Practices", @@ -80624,7 +88717,7 @@ module.exports = { } }; -},{}],285:[function(require,module,exports){ +},{}],284:[function(require,module,exports){ /** * @fileoverview Rule to count multiple spaces in regular expressions * @author Matt DuVall @@ -80632,7 +88725,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -80640,6 +88733,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow multiple spaces in regular expressions", category: "Possible Errors", @@ -80648,7 +88743,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -80737,7 +88831,7 @@ module.exports = { } }; -},{"../ast-utils":115}],286:[function(require,module,exports){ +},{"../util/ast-utils":405}],285:[function(require,module,exports){ /** * @fileoverview Restrict usage of specified globals. * @author Benoît Zugmeyer @@ -80757,6 +88851,8 @@ var DEFAULT_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'.", module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified global variables", category: "Variables", @@ -80829,7 +88925,7 @@ module.exports = { * @private */ function isRestricted(name) { - return restrictedGlobalMessages.hasOwnProperty(name); + return Object.prototype.hasOwnProperty.call(restrictedGlobalMessages, name); } return { @@ -80854,7 +88950,7 @@ module.exports = { } }; -},{}],287:[function(require,module,exports){ +},{}],286:[function(require,module,exports){ /** * @fileoverview Restrict usage of specified node imports. * @author Guy Ellis @@ -80909,6 +89005,8 @@ var arrayOfStringsOrObjects = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified modules when loaded by `import`", category: "ECMAScript 6", @@ -80934,7 +89032,7 @@ module.exports = { create: function create(context) { var options = Array.isArray(context.options) ? context.options : []; - var isPathAndPatternsObject = _typeof(options[0]) === "object" && (options[0].hasOwnProperty("paths") || options[0].hasOwnProperty("patterns")); + var isPathAndPatternsObject = _typeof(options[0]) === "object" && (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns")); var restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || []; var restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || []; @@ -81040,7 +89138,7 @@ module.exports = { /** * Check if the given importNames are restricted given a list of restrictedImportNames. * @param {Set.} importNames - Set of import names that are being imported - * @param {[string]} restrictedImportNames - array of import names that are restricted for this import + * @param {string[]} restrictedImportNames - array of import names that are restricted for this import * @returns {boolean} whether the objectName is restricted * @private */ @@ -81081,36 +89179,53 @@ module.exports = { return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource); } - return { - ImportDeclaration: function ImportDeclaration(node) { - var importSource = node.source.value.trim(); - var importNames = node.specifiers.reduce(function (set, specifier) { - if (specifier.type === "ImportDefaultSpecifier") { - set.add("default"); - } else if (specifier.type === "ImportNamespaceSpecifier") { - set.add("*"); - } else { - set.add(specifier.imported.name); - } - return set; - }, new Set()); + /** + * Checks a node to see if any problems should be reported. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function checkNode(node) { + var importSource = node.source.value.trim(); + var importNames = node.specifiers ? node.specifiers.reduce(function (set, specifier) { + if (specifier.type === "ImportDefaultSpecifier") { + set.add("default"); + } else if (specifier.type === "ImportNamespaceSpecifier") { + set.add("*"); + } else if (specifier.imported) { + set.add(specifier.imported.name); + } else if (specifier.local) { + set.add(specifier.local.name); + } + return set; + }, new Set()) : new Set(); - if (isRestrictedForEverythingImported(importSource, importNames)) { - reportPathForEverythingImported(importSource, node); - } - - if (isRestrictedPath(importSource, importNames)) { - reportPath(node); - } - if (isRestrictedPattern(importSource)) { - reportPathForPatterns(node); - } + if (isRestrictedForEverythingImported(importSource, importNames)) { + reportPathForEverythingImported(importSource, node); } + + if (isRestrictedPath(importSource, importNames)) { + reportPath(node); + } + if (isRestrictedPattern(importSource)) { + reportPathForPatterns(node); + } + } + + return { + ImportDeclaration: checkNode, + ExportNamedDeclaration: function ExportNamedDeclaration(node) { + if (node.source) { + checkNode(node); + } + }, + + ExportAllDeclaration: checkNode }; } }; -},{"ignore":84}],288:[function(require,module,exports){ +},{"ignore":86}],287:[function(require,module,exports){ /** * @fileoverview Restrict usage of specified node modules. * @author Christian Schulz @@ -81159,6 +89274,8 @@ var arrayOfStringsOrObjects = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified modules when loaded by `require`", category: "Node.js and CommonJS", @@ -81184,7 +89301,7 @@ module.exports = { create: function create(context) { var options = Array.isArray(context.options) ? context.options : []; - var isPathAndPatternsObject = _typeof(options[0]) === "object" && (options[0].hasOwnProperty("paths") || options[0].hasOwnProperty("patterns")); + var isPathAndPatternsObject = _typeof(options[0]) === "object" && (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns")); var restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || []; var restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || []; @@ -81281,7 +89398,7 @@ module.exports = { } }; -},{"ignore":84}],289:[function(require,module,exports){ +},{"ignore":86}],288:[function(require,module,exports){ /** * @fileoverview Rule to disallow certain object properties * @author Will Klein & Eli White @@ -81289,7 +89406,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -81297,6 +89414,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow certain properties on certain objects", category: "Best Practices", @@ -81456,7 +89575,7 @@ module.exports = { } }; -},{"../ast-utils":115}],290:[function(require,module,exports){ +},{"../util/ast-utils":405}],289:[function(require,module,exports){ /** * @fileoverview Rule to flag use of certain node types * @author Burak Yigit Kaya @@ -81471,6 +89590,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified syntax", category: "Stylistic Issues", @@ -81517,7 +89638,7 @@ module.exports = { } }; -},{}],291:[function(require,module,exports){ +},{}],290:[function(require,module,exports){ /** * @fileoverview Rule to flag when return statement contains assignment * @author Ilya Volodin @@ -81528,7 +89649,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -81542,6 +89663,8 @@ var SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExp module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow assignment operators in `return` statements", category: "Best Practices", @@ -81564,11 +89687,12 @@ module.exports = { return; } - var parent = node.parent; + var currentChild = node; + var parent = currentChild.parent; // Find ReturnStatement or ArrowFunctionExpression in ancestors. while (parent && !SENTINEL_TYPE.test(parent.type)) { - node = parent; + currentChild = parent; parent = parent.parent; } @@ -81578,7 +89702,7 @@ module.exports = { node: parent, message: "Return statement should not contain assignment." }); - } else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === node) { + } else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === currentChild) { context.report({ node: parent, message: "Arrow function should not return assignment." @@ -81589,14 +89713,14 @@ module.exports = { } }; -},{"../ast-utils":115}],292:[function(require,module,exports){ +},{"../util/ast-utils":405}],291:[function(require,module,exports){ /** * @fileoverview Disallows unnecessary `return await` * @author Jordan Harband */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -81606,16 +89730,19 @@ var message = "Redundant use of `await` on a return value."; module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary `return await`", category: "Best Practices", - // TODO: set to true recommended: false, url: "https://eslint.org/docs/rules/no-return-await" }, + fixable: null, + schema: [] }, @@ -81688,7 +89815,7 @@ module.exports = { } }; -},{"../ast-utils":115}],293:[function(require,module,exports){ +},{"../util/ast-utils":405}],292:[function(require,module,exports){ /** * @fileoverview Rule to flag when using javascript: urls * @author Ilya Volodin @@ -81704,6 +89831,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `javascript:` urls", category: "Best Practices", @@ -81730,7 +89859,7 @@ module.exports = { } }; -},{}],294:[function(require,module,exports){ +},{}],293:[function(require,module,exports){ /** * @fileoverview Rule to disallow assignments where both sides are exactly the same * @author Toru Nagashima @@ -81742,7 +89871,9 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -81862,6 +89993,8 @@ function eachSelfAssignment(left, right, props, report) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow assignments where both sides are exactly the same", category: "Best Practices", @@ -81882,8 +90015,13 @@ module.exports = { create: function create(context) { var sourceCode = context.getSourceCode(); - var options = context.options[0]; - var props = Boolean(options && options.props); + + var _context$options = _slicedToArray(context.options, 1), + _context$options$ = _context$options[0]; + + _context$options$ = _context$options$ === undefined ? {} : _context$options$; + var _context$options$$pro = _context$options$.props, + props = _context$options$$pro === undefined ? true : _context$options$$pro; /** * Reports a given node as self assignments. @@ -81891,6 +90029,7 @@ module.exports = { * @param {ASTNode} node - A node to report. This is an Identifier node. * @returns {void} */ + function report(node) { context.report({ node: node, @@ -81911,7 +90050,7 @@ module.exports = { } }; -},{"../ast-utils":115}],295:[function(require,module,exports){ +},{"../util/ast-utils":405}],294:[function(require,module,exports){ /** * @fileoverview Rule to flag comparison where left part is the same as the right * part. @@ -81926,6 +90065,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow comparisons where both sides are exactly the same", category: "Best Practices", @@ -81966,7 +90107,7 @@ module.exports = { } }; -},{}],296:[function(require,module,exports){ +},{}],295:[function(require,module,exports){ /** * @fileoverview Rule to flag use of comma operator * @author Brandon Mills @@ -81978,7 +90119,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -81986,6 +90127,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow comma operators", category: "Best Practices", @@ -82076,7 +90219,7 @@ module.exports = { } }; -},{"../ast-utils":115}],297:[function(require,module,exports){ +},{"../util/ast-utils":405}],296:[function(require,module,exports){ /** * @fileoverview Disallow shadowing of NaN, undefined, and Infinity (ES5 section 15.1.1) * @author Michael Ficarra @@ -82089,6 +90232,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow identifiers from shadowing restricted names", category: "Variables", @@ -82103,51 +90248,46 @@ module.exports = { var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; - /** - * Check if the node name is present inside the restricted list - * @param {ASTNode} id id to evaluate - * @returns {void} - * @private - */ - function checkForViolation(id) { - if (RESTRICTED.indexOf(id.name) > -1) { - context.report({ - node: id, - message: "Shadowing of global property '{{idName}}'.", - data: { - idName: id.name - } - }); - } - } - return { - VariableDeclarator: function VariableDeclarator(node) { - checkForViolation(node.id); - }, - ArrowFunctionExpression: function ArrowFunctionExpression(node) { - [].map.call(node.params, checkForViolation); - }, - FunctionExpression: function FunctionExpression(node) { - if (node.id) { - checkForViolation(node.id); + "VariableDeclaration, :function, CatchClause": function VariableDeclarationFunctionCatchClause(node) { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = context.getDeclaredVariables(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var variable = _step.value; + + if (variable.defs.length > 0 && RESTRICTED.includes(variable.name)) { + context.report({ + node: variable.defs[0].name, + message: "Shadowing of global property '{{idName}}'.", + data: { + idName: variable.name + } + }); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } } - [].map.call(node.params, checkForViolation); - }, - FunctionDeclaration: function FunctionDeclaration(node) { - if (node.id) { - checkForViolation(node.id); - [].map.call(node.params, checkForViolation); - } - }, - CatchClause: function CatchClause(node) { - checkForViolation(node.param); } }; } }; -},{}],298:[function(require,module,exports){ +},{}],297:[function(require,module,exports){ /** * @fileoverview Rule to flag on declaring variables already declared in the outer scope * @author Ilya Volodin @@ -82159,7 +90299,9 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -82167,6 +90309,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow variable declarations from shadowing variables declared in the outer scope", category: "Variables", @@ -82309,7 +90453,7 @@ module.exports = { while (stack.length) { var scope = stack.pop(); - stack.push.apply(stack, scope.childScopes); + stack.push.apply(stack, _toConsumableArray(scope.childScopes)); checkForShadows(scope); } } @@ -82317,7 +90461,7 @@ module.exports = { } }; -},{"../ast-utils":115}],299:[function(require,module,exports){ +},{"../util/ast-utils":405}],298:[function(require,module,exports){ /** * @fileoverview Rule to check that spaced function application * @author Matt DuVall @@ -82332,16 +90476,19 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "disallow spacing between function identifiers and their applications (deprecated)", category: "Stylistic Issues", recommended: false, - replacedBy: ["func-call-spacing"], url: "https://eslint.org/docs/rules/no-spaced-func" }, deprecated: true, + replacedBy: ["func-call-spacing"], + fixable: "whitespace", schema: [] }, @@ -82387,7 +90534,7 @@ module.exports = { } }; -},{}],300:[function(require,module,exports){ +},{}],299:[function(require,module,exports){ /** * @fileoverview Disallow sparse arrays * @author Nicholas C. Zakas @@ -82400,6 +90547,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow sparse arrays", category: "Possible Errors", @@ -82429,7 +90578,7 @@ module.exports = { } }; -},{}],301:[function(require,module,exports){ +},{}],300:[function(require,module,exports){ /** * @fileoverview Rule to check for properties whose identifier ends with the string Sync * @author Matt DuVall @@ -82447,6 +90596,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow synchronous methods", category: "Node.js and CommonJS", @@ -82480,7 +90631,7 @@ module.exports = { } }; -},{}],302:[function(require,module,exports){ +},{}],301:[function(require,module,exports){ /** * @fileoverview Rule to check for tabs inside a file * @author Gyandeep Singh @@ -82492,7 +90643,8 @@ module.exports = { // Helpers //------------------------------------------------------------------------------ -var regex = /\t/; +var tabRegex = /\t+/g; +var anyNonWhitespaceRegex = /\S/; //------------------------------------------------------------------------------ // Public Interface @@ -82500,27 +90652,44 @@ var regex = /\t/; module.exports = { meta: { + type: "layout", + docs: { description: "disallow all tabs", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/no-tabs" }, - schema: [] + schema: [{ + type: "object", + properties: { + allowIndentationTabs: { + type: "boolean" + } + }, + additionalProperties: false + }] }, create: function create(context) { + var sourceCode = context.getSourceCode(); + var allowIndentationTabs = context.options && context.options[0] && context.options[0].allowIndentationTabs; + return { Program: function Program(node) { - context.getSourceCode().getLines().forEach(function (line, index) { - var match = regex.exec(line); + sourceCode.getLines().forEach(function (line, index) { + var match = void 0; + + while ((match = tabRegex.exec(line)) !== null) { + if (allowIndentationTabs && !anyNonWhitespaceRegex.test(line.slice(0, match.index))) { + continue; + } - if (match) { context.report({ node: node, loc: { line: index + 1, - column: match.index + 1 + column: match.index }, message: "Unexpected tab character." }); @@ -82531,7 +90700,7 @@ module.exports = { } }; -},{}],303:[function(require,module,exports){ +},{}],302:[function(require,module,exports){ /** * @fileoverview Warn when using template string syntax in regular strings * @author Jeroen Engels @@ -82544,6 +90713,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "disallow template literal placeholder syntax in regular strings", category: "Possible Errors", @@ -82570,7 +90741,7 @@ module.exports = { } }; -},{}],304:[function(require,module,exports){ +},{}],303:[function(require,module,exports){ /** * @fileoverview Rule to flag use of ternary operators. * @author Ian Christian Myers @@ -82584,6 +90755,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow ternary operators", category: "Stylistic Issues", @@ -82604,7 +90777,7 @@ module.exports = { } }; -},{}],305:[function(require,module,exports){ +},{}],304:[function(require,module,exports){ /** * @fileoverview A rule to disallow using `this`/`super` before `super()`. * @author Toru Nagashima @@ -82616,7 +90789,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -82639,6 +90812,8 @@ function isConstructorFunction(node) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow `this`/`super` before calling `super()` in constructors", category: "ECMAScript 6", @@ -82767,7 +90942,6 @@ module.exports = { * invalid node. * * @param {CodePath} codePath - A code path which was ended. - * @param {ASTNode} node - The current node. * @returns {void} */ onCodePathEnd: function onCodePathEnd(codePath) { @@ -82894,7 +91068,7 @@ module.exports = { } }; -},{"../ast-utils":115}],306:[function(require,module,exports){ +},{"../util/ast-utils":405}],305:[function(require,module,exports){ /** * @fileoverview Rule to restrict what can be thrown as an exception. * @author Dieter Oberkofler @@ -82902,7 +91076,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -82910,6 +91084,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow throwing literals as exceptions", category: "Best Practices", @@ -82936,7 +91112,7 @@ module.exports = { } }; -},{"../ast-utils":115}],307:[function(require,module,exports){ +},{"../util/ast-utils":405}],306:[function(require,module,exports){ /** * @fileoverview Disallow trailing spaces at the end of lines. * @author Nodeca Team @@ -82947,7 +91123,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -82955,6 +91131,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "disallow trailing whitespace at the end of lines", category: "Stylistic Issues", @@ -83104,7 +91282,7 @@ module.exports = { } }; -},{"../ast-utils":115}],308:[function(require,module,exports){ +},{"../util/ast-utils":405}],307:[function(require,module,exports){ /** * @fileoverview Rule to flag when initializing to undefined * @author Ilya Volodin @@ -83112,7 +91290,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -83120,6 +91298,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow initializing variables to `undefined`", category: "Variables", @@ -83128,7 +91308,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -83168,7 +91347,7 @@ module.exports = { } }; -},{"../ast-utils":115}],309:[function(require,module,exports){ +},{"../util/ast-utils":405}],308:[function(require,module,exports){ /** * @fileoverview Rule to flag references to undeclared variables. * @author Mark Macdonald @@ -83197,6 +91376,8 @@ function hasTypeOfOperator(node) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow the use of undeclared variables unless mentioned in `/*global */` comments", category: "Variables", @@ -83241,7 +91422,7 @@ module.exports = { } }; -},{}],310:[function(require,module,exports){ +},{}],309:[function(require,module,exports){ /** * @fileoverview Rule to flag references to the undefined variable. * @author Michael Ficarra @@ -83252,8 +91433,12 @@ module.exports = { // Rule Definition //------------------------------------------------------------------------------ +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow the use of `undefined` as an identifier", category: "Variables", @@ -83316,7 +91501,7 @@ module.exports = { while (stack.length) { var scope = stack.pop(); - stack.push.apply(stack, scope.childScopes); + stack.push.apply(stack, _toConsumableArray(scope.childScopes)); checkScope(scope); } } @@ -83324,7 +91509,7 @@ module.exports = { } }; -},{}],311:[function(require,module,exports){ +},{}],310:[function(require,module,exports){ /** * @fileoverview Rule to flag trailing underscores in variable declarations. * @author Matt DuVall @@ -83338,6 +91523,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow dangling underscores in identifiers", category: "Stylistic Issues", @@ -83525,7 +91712,7 @@ module.exports = { } }; -},{}],312:[function(require,module,exports){ +},{}],311:[function(require,module,exports){ /** * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not. * @author Glen Mailer @@ -83536,7 +91723,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -83544,6 +91731,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow confusing multiline expressions", category: "Possible Errors", @@ -83561,7 +91750,7 @@ module.exports = { var TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; var DIVISION_MESSAGE = "Unexpected newline between numerator and division operator."; - var REGEX_FLAG_MATCHER = /^[gimuy]+$/; + var REGEX_FLAG_MATCHER = /^[gimsuy]+$/; var sourceCode = context.getSourceCode(); @@ -83619,7 +91808,7 @@ module.exports = { } }; -},{"../ast-utils":115}],313:[function(require,module,exports){ +},{"../util/ast-utils":405}],312:[function(require,module,exports){ /** * @fileoverview Rule to disallow use of unmodified expressions in loop conditions * @author Toru Nagashima @@ -83631,14 +91820,15 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + var Traverser = require("../util/traverser"), - astUtils = require("../ast-utils"); + astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -var pushAll = Function.apply.bind(Array.prototype.push); var SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/; var LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property. var GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/; @@ -83782,6 +91972,8 @@ function updateModifiedFlag(conditions, modifiers) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow unmodified loop conditions", category: "Best Practices", @@ -83967,7 +92159,7 @@ module.exports = { var scope = void 0; while (scope = queue.pop()) { - pushAll(queue, scope.childScopes); + queue.push.apply(queue, _toConsumableArray(scope.childScopes)); scope.variables.forEach(checkReferences); } @@ -83978,7 +92170,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/traverser":412}],314:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/traverser":418}],313:[function(require,module,exports){ /** * @fileoverview Rule to flag no-unneeded-ternary * @author Gyandeep Singh @@ -83986,7 +92178,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); // Operators that always result in a boolean value var BOOLEAN_OPERATORS = new Set(["==", "===", "!=", "!==", ">", ">=", "<", "<=", "in", "instanceof"]); @@ -84005,6 +92197,8 @@ var OPERATOR_INVERSES = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow ternary operators when simpler alternatives exist", category: "Stylistic Issues", @@ -84112,7 +92306,7 @@ module.exports = { fix: function fix(fixer) { var nodeAlternate = astUtils.getParenthesisedText(sourceCode, node.alternate); - if (node.alternate.type === "ConditionalExpression") { + if (node.alternate.type === "ConditionalExpression" || node.alternate.type === "YieldExpression") { var isAlternateParenthesised = astUtils.isParenthesised(sourceCode, node.alternate); nodeAlternate = isAlternateParenthesised ? nodeAlternate : "(" + nodeAlternate + ")"; @@ -84127,7 +92321,7 @@ module.exports = { } }; -},{"../ast-utils":115}],315:[function(require,module,exports){ +},{"../util/ast-utils":405}],314:[function(require,module,exports){ /** * @fileoverview Checks for unreachable code due to return, throws, break, and continue. * @author Joel Feenstra @@ -84258,6 +92452,8 @@ var ConsecutiveRange = function () { module.exports = { meta: { + type: "problem", + docs: { description: "disallow unreachable code after `return`, `throw`, `continue`, and `break` statements", category: "Possible Errors", @@ -84337,7 +92533,6 @@ module.exports = { ContinueStatement: reportIfUnreachable, DebuggerStatement: reportIfUnreachable, DoWhileStatement: reportIfUnreachable, - EmptyStatement: reportIfUnreachable, ExpressionStatement: reportIfUnreachable, ForInStatement: reportIfUnreachable, ForOfStatement: reportIfUnreachable, @@ -84370,7 +92565,7 @@ module.exports = { } }; -},{}],316:[function(require,module,exports){ +},{}],315:[function(require,module,exports){ /** * @fileoverview Rule to flag unsafe statements in finally block * @author Onur Temizkan @@ -84392,6 +92587,8 @@ var SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration| module.exports = { meta: { + type: "problem", + docs: { description: "disallow control flow statements in `finally` blocks", category: "Possible Errors", @@ -84432,17 +92629,16 @@ module.exports = { sentinelNodeType = SENTINEL_NODE_TYPE_RETURN_THROW; } - while (node && !sentinelNodeType.test(node.type)) { - if (node.parent.label && label && node.parent.label.name === label.name) { + for (var currentNode = node; currentNode && !sentinelNodeType.test(currentNode.type); currentNode = currentNode.parent) { + if (currentNode.parent.label && label && currentNode.parent.label.name === label.name) { labelInside = true; } - if (isFinallyBlock(node)) { + if (isFinallyBlock(currentNode)) { if (label && labelInside) { return false; } return true; } - node = node.parent; } return false; } @@ -84476,7 +92672,7 @@ module.exports = { } }; -},{}],317:[function(require,module,exports){ +},{}],316:[function(require,module,exports){ /** * @fileoverview Rule to disallow negating the left operand of relational operators * @author Toru Nagashima @@ -84488,7 +92684,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -84520,12 +92716,15 @@ function isNegation(node) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow negating the left operand of relational operators", category: "Possible Errors", recommended: true, url: "https://eslint.org/docs/rules/no-unsafe-negation" }, + schema: [], fixable: "code" }, @@ -84556,7 +92755,7 @@ module.exports = { } }; -},{"../ast-utils":115}],318:[function(require,module,exports){ +},{"../util/ast-utils":405}],317:[function(require,module,exports){ /** * @fileoverview Flag expressions in statement position that do not side effect * @author Michael Ficarra @@ -84569,6 +92768,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unused expressions", category: "Best Practices", @@ -84679,7 +92880,7 @@ module.exports = { } }; -},{}],319:[function(require,module,exports){ +},{}],318:[function(require,module,exports){ /** * @fileoverview Rule to disallow unused labels. * @author Toru Nagashima @@ -84693,6 +92894,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unused labels", category: "Best Practices", @@ -84701,7 +92904,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -84787,7 +92989,7 @@ module.exports = { } }; -},{}],320:[function(require,module,exports){ +},{}],319:[function(require,module,exports){ /** * @fileoverview Rule to flag declared but unused variables * @author Ilya Volodin @@ -84800,7 +93002,7 @@ module.exports = { //------------------------------------------------------------------------------ var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -84808,6 +93010,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "problem", + docs: { description: "disallow unused variables", category: "Variables", @@ -85003,6 +93207,33 @@ module.exports = { return false; } + /** + * Gets a list of function definitions for a specified variable. + * @param {Variable} variable - eslint-scope variable object. + * @returns {ASTNode[]} Function nodes. + * @private + */ + function getFunctionDefinitions(variable) { + var functionDefinitions = []; + + variable.defs.forEach(function (def) { + var type = def.type, + node = def.node; + + // FunctionDeclarations + + if (type === "FunctionName") { + functionDefinitions.push(node); + } + + // FunctionExpressions + if (type === "Variable" && node.init && (node.init.type === "FunctionExpression" || node.init.type === "ArrowFunctionExpression")) { + functionDefinitions.push(node.init); + } + }); + return functionDefinitions; + } + /** * Checks the position of given nodes. * @@ -85141,10 +93372,8 @@ module.exports = { return ref.isRead() && ( // self update. e.g. `a += 1`, `a++` - parent.type === "AssignmentExpression" && granpa.type === "ExpressionStatement" && parent.left === id || parent.type === "UpdateExpression" && granpa.type === "ExpressionStatement" || - // in RHS of an assignment for itself. e.g. `a = a + 1` - rhsNode && isInside(id, rhsNode) && !isInsideOfStorableFunction(id, rhsNode)); + parent.type === "AssignmentExpression" && granpa.type === "ExpressionStatement" && parent.left === id || parent.type === "UpdateExpression" && granpa.type === "ExpressionStatement" || rhsNode && isInside(id, rhsNode) && !isInsideOfStorableFunction(id, rhsNode)); } /** @@ -85190,11 +93419,7 @@ module.exports = { * @private */ function isUsedVariable(variable) { - var functionNodes = variable.defs.filter(function (def) { - return def.type === "FunctionName"; - }).map(function (def) { - return def.node; - }), + var functionNodes = getFunctionDefinitions(variable), isFunctionDefinition = functionNodes.length > 0; var rhsNode = null; @@ -85212,32 +93437,21 @@ module.exports = { } /** - * Checks whether the given variable is the last parameter in the non-ignored parameters. + * Checks whether the given variable is after the last used parameter. * * @param {eslint-scope.Variable} variable - The variable to check. - * @returns {boolean} `true` if the variable is the last. + * @returns {boolean} `true` if the variable is defined after the last + * used parameter. */ - function isLastInNonIgnoredParameters(variable) { + function isAfterLastUsedArg(variable) { var def = variable.defs[0]; + var params = context.getDeclaredVariables(def.node); + var posteriorParams = params.slice(params.indexOf(variable) + 1); - // This is the last. - if (def.index === def.node.params.length - 1) { - return true; - } - - // if all parameters preceded by this variable are ignored and unused, this is the last. - if (config.argsIgnorePattern) { - var params = context.getDeclaredVariables(def.node); - var posteriorParams = params.slice(params.indexOf(variable) + 1); - - if (posteriorParams.every(function (v) { - return v.references.length === 0 && config.argsIgnorePattern.test(v.name); - })) { - return true; - } - } - - return false; + // If any used parameters occur after this parameter, do not report. + return !posteriorParams.some(function (v) { + return v.references.length > 0 || v.eslintUsed; + }); } /** @@ -85307,8 +93521,8 @@ module.exports = { continue; } - // if "args" option is "after-used", skip all but the last parameter - if (config.args === "after-used" && astUtils.isFunction(def.name.parent) && !isLastInNonIgnoredParameters(variable)) { + // if "args" option is "after-used", skip used variables + if (config.args === "after-used" && astUtils.isFunction(def.name.parent) && !isAfterLastUsedArg(variable)) { continue; } } else { @@ -85399,7 +93613,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],321:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],320:[function(require,module,exports){ /** * @fileoverview Rule to flag use of variables before they are defined * @author Ilya Volodin @@ -85532,6 +93746,8 @@ function isInInitializer(variable, reference) { module.exports = { meta: { + type: "problem", + docs: { description: "disallow the use of variables before they are defined", category: "Variables", @@ -85605,51 +93821,19 @@ module.exports = { data: reference.identifier }); }); + + scope.childScopes.forEach(findVariablesInScope); } - /** - * Validates variables inside of a node's scope. - * @param {ASTNode} node The node to check. - * @returns {void} - * @private - */ - function findVariables() { - var scope = context.getScope(); - - findVariablesInScope(scope); - } - - var ruleDefinition = { - "Program:exit": function ProgramExit(node) { - var scope = context.getScope(), - ecmaFeatures = context.parserOptions.ecmaFeatures || {}; - - findVariablesInScope(scope); - - // both Node.js and Modules have an extra scope - if (ecmaFeatures.globalReturn || node.sourceType === "module") { - findVariablesInScope(scope.childScopes[0]); - } + return { + Program: function Program() { + findVariablesInScope(context.getScope()); } }; - - if (context.parserOptions.ecmaVersion >= 6) { - ruleDefinition["BlockStatement:exit"] = ruleDefinition["SwitchStatement:exit"] = findVariables; - - ruleDefinition["ArrowFunctionExpression:exit"] = function (node) { - if (node.body.type !== "BlockStatement") { - findVariables(); - } - }; - } else { - ruleDefinition["FunctionExpression:exit"] = ruleDefinition["FunctionDeclaration:exit"] = ruleDefinition["ArrowFunctionExpression:exit"] = findVariables; - } - - return ruleDefinition; } }; -},{}],322:[function(require,module,exports){ +},{}],321:[function(require,module,exports){ /** * @fileoverview A rule to disallow unnecessary `.call()` and `.apply()`. * @author Toru Nagashima @@ -85657,7 +93841,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -85692,6 +93876,8 @@ function isValidThisArg(expectedThis, thisArg, sourceCode) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary calls to `.call()` and `.apply()`", category: "Best Practices", @@ -85723,7 +93909,54 @@ module.exports = { } }; -},{"../ast-utils":115}],323:[function(require,module,exports){ +},{"../util/ast-utils":405}],322:[function(require,module,exports){ +/** + * @fileoverview Reports useless `catch` clauses that just rethrow their error. + * @author Teddy Katz + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "disallow unnecessary `catch` clauses", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/no-useless-catch" + }, + + schema: [] + }, + + create: function create(context) { + return { + CatchClause: function CatchClause(node) { + if (node.param && node.param.type === "Identifier" && node.body.body.length && node.body.body[0].type === "ThrowStatement" && node.body.body[0].argument.type === "Identifier" && node.body.body[0].argument.name === node.param.name) { + if (node.parent.finalizer) { + context.report({ + node: node, + message: "Unnecessary catch clause." + }); + } else { + context.report({ + node: node.parent, + message: "Unnecessary try/catch wrapper." + }); + } + } + } + }; + } +}; + +},{}],323:[function(require,module,exports){ /** * @fileoverview Rule to disallow unnecessary computed property keys in object literals * @author Burak Yigit Kaya @@ -85736,7 +93969,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -85746,6 +93979,8 @@ var MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property} module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary computed property keys in object literals", category: "ECMAScript 6", @@ -85754,7 +93989,6 @@ module.exports = { }, schema: [], - fixable: "code" }, create: function create(context) { @@ -85803,7 +94037,7 @@ module.exports = { } }; -},{"../ast-utils":115}],324:[function(require,module,exports){ +},{"../util/ast-utils":405}],324:[function(require,module,exports){ /** * @fileoverview disallow unncessary concatenation of template strings * @author Henry Zhu @@ -85814,7 +94048,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -85872,6 +94106,8 @@ function getRight(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary concatenation of literals or template literals", category: "Best Practices", @@ -85911,7 +94147,7 @@ module.exports = { } }; -},{"../ast-utils":115}],325:[function(require,module,exports){ +},{"../util/ast-utils":405}],325:[function(require,module,exports){ /** * @fileoverview Rule to flag the use of redundant constructors in classes. * @author Alberto Rodríguez @@ -86029,6 +94265,8 @@ function isRedundantSuperCall(body, ctorParams) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary constructors", category: "ECMAScript 6", @@ -86077,7 +94315,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -86110,8 +94348,8 @@ function union(setA, setB) { } var VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS); -var REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnrsStvwWxu0123456789]"); -var REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()B")); +var REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnpPrsStvwWxu0123456789]"); +var REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()Bk")); /** * Parses a regular expression into a list of characters with character class info. @@ -86164,6 +94402,8 @@ function parseRegExp(regExpText) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow unnecessary escape characters", category: "Best Practices", @@ -86253,7 +94493,7 @@ module.exports = { * JSXAttribute doesn't have any escape sequence: https://facebook.github.io/jsx/. * In addition, backticks are not supported by JSX yet: https://github.com/facebook/jsx/issues/25. */ - if (node.parent.type === "JSXAttribute" || node.parent.type === "JSXElement") { + if (node.parent.type === "JSXAttribute" || node.parent.type === "JSXElement" || node.parent.type === "JSXFragment") { return; } @@ -86311,7 +94551,7 @@ module.exports = { } }; -},{"../ast-utils":115}],327:[function(require,module,exports){ +},{"../util/ast-utils":405}],327:[function(require,module,exports){ /** * @fileoverview Disallow renaming import, export, and destructured assignments to the same name. * @author Kai Cataldo @@ -86325,13 +94565,17 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow renaming import, export, and destructured assignments to the same name", category: "ECMAScript 6", recommended: false, url: "https://eslint.org/docs/rules/no-useless-rename" }, + fixable: "code", + schema: [{ type: "object", properties: { @@ -86463,22 +94707,15 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"), +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var astUtils = require("../util/ast-utils"), FixTracker = require("../util/fix-tracker"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -/** - * Adds all elements of 2nd argument into 1st argument. - * - * @param {Array} array - The destination array to add. - * @param {Array} elements - The source array to add. - * @returns {void} - */ -var pushAll = Function.apply.bind(Array.prototype.push); - /** * Removes the given element from the array. * @@ -86511,12 +94748,10 @@ function isRemovable(node) { * @returns {boolean} `true` if the node is in a `finally` block. */ function isInFinally(node) { - while (node && node.parent && !astUtils.isFunction(node)) { - if (node.parent.type === "TryStatement" && node.parent.finalizer === node) { + for (var currentNode = node; currentNode && currentNode.parent && !astUtils.isFunction(currentNode); currentNode = currentNode.parent) { + if (currentNode.parent.type === "TryStatement" && currentNode.parent.finalizer === currentNode) { return true; } - - node = node.parent; } return false; @@ -86528,12 +94763,15 @@ function isInFinally(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow redundant return statements", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/no-useless-return" }, + fixable: "code", schema: [] }, @@ -86571,13 +94809,12 @@ module.exports = { * * @param {ASTNode[]} uselessReturns - The collected return statements. * @param {CodePathSegment[]} prevSegments - The previous segments to traverse. - * @param {WeakSet} [traversedSegments] A set of segments that have already been traversed in this call + * @param {WeakSet} [providedTraversedSegments] A set of segments that have already been traversed in this call * @returns {ASTNode[]} `uselessReturns`. */ - function getUselessReturns(uselessReturns, prevSegments, traversedSegments) { - if (!traversedSegments) { - traversedSegments = new WeakSet(); - } + function getUselessReturns(uselessReturns, prevSegments, providedTraversedSegments) { + var traversedSegments = providedTraversedSegments || new WeakSet(); + var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; @@ -86594,7 +94831,7 @@ module.exports = { continue; } - pushAll(uselessReturns, segmentInfoMap.get(segment).uselessReturns); + uselessReturns.push.apply(uselessReturns, _toConsumableArray(segmentInfoMap.get(segment).uselessReturns)); } } catch (err) { _didIteratorError = true; @@ -86843,7 +95080,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/fix-tracker":403}],329:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/fix-tracker":407}],329:[function(require,module,exports){ /** * @fileoverview Rule to check for the usage of var. * @author Jamund Ferguson @@ -86855,7 +95092,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -86879,10 +95116,12 @@ function isGlobal(variable) { * scope. */ function getEnclosingFunctionScope(scope) { - while (scope.type !== "function" && scope.type !== "global") { - scope = scope.upper; + var currentScope = scope; + + while (currentScope.type !== "function" && currentScope.type !== "global") { + currentScope = currentScope.upper; } - return scope; + return currentScope; } /** @@ -86935,12 +95174,10 @@ var SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|F * `ForOfStatement`. */ function getScopeNode(node) { - while (node) { - if (SCOPE_NODE_TYPE.test(node.type)) { - return node; + for (var currentNode = node; currentNode; currentNode = currentNode.parent) { + if (SCOPE_NODE_TYPE.test(currentNode.type)) { + return currentNode; } - - node = node.parent; } /* istanbul ignore next : unreachable */ @@ -87024,6 +95261,8 @@ function hasReferenceInTDZ(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `let` or `const` instead of `var`", category: "ECMAScript 6", @@ -87163,7 +95402,7 @@ module.exports = { } }; -},{"../ast-utils":115}],330:[function(require,module,exports){ +},{"../util/ast-utils":405}],330:[function(require,module,exports){ /** * @fileoverview Rule to disallow use of void operator. * @author Mike Sidorov @@ -87176,6 +95415,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `void` operators", category: "Best Practices", @@ -87210,7 +95451,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -87218,6 +95459,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow specified warning terms in comments", category: "Best Practices", @@ -87260,6 +95503,8 @@ module.exports = { */ function convertToRegExp(term) { var escaped = term.replace(/[-/\\$^*+?.()|[\]{}]/g, "\\$&"); + var wordBoundary = "\\b"; + var eitherOrWordBoundary = "|" + wordBoundary; var prefix = void 0; /* @@ -87282,12 +95527,27 @@ module.exports = { */ prefix = "^\\s*"; } else if (/^\w/.test(term)) { - prefix = "\\b"; + prefix = wordBoundary; } else { prefix = ""; } - return new RegExp(prefix + escaped + suffix, "i"); + if (location === "start") { + + /* + * For location "start" the regex should be + * ^\s*TERM\b. This checks the word boundary + * at the beginning of the comment. + */ + return new RegExp(prefix + escaped + suffix, "i"); + } + + /* + * For location "anywhere" the regex should be + * \bTERM\b|\bTERM\b, this checks the entire comment + * for the term. + */ + return new RegExp(prefix + escaped + suffix + eitherOrWordBoundary + term + wordBoundary, "i"); } var warningRegExps = warningTerms.map(convertToRegExp); @@ -87344,7 +95604,7 @@ module.exports = { } }; -},{"../ast-utils":115}],332:[function(require,module,exports){ +},{"../util/ast-utils":405}],332:[function(require,module,exports){ /** * @fileoverview Rule to disallow whitespace before properties * @author Kai Cataldo @@ -87355,7 +95615,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -87363,6 +95623,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "disallow whitespace before properties", category: "Stylistic Issues", @@ -87441,7 +95703,7 @@ module.exports = { } }; -},{"../ast-utils":115}],333:[function(require,module,exports){ +},{"../util/ast-utils":405}],333:[function(require,module,exports){ /** * @fileoverview Rule to flag use of with statement * @author Nicholas C. Zakas @@ -87455,6 +95717,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `with` statements", category: "Best Practices", @@ -87490,13 +95754,17 @@ var POSITION_SCHEMA = { enum: ["beside", "below", "any"] }; module.exports = { meta: { + type: "layout", + docs: { description: "enforce the location of single-line statements", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/nonblock-statement-body-position" }, + fixable: "whitespace", + schema: [POSITION_SCHEMA, { properties: { overrides: { @@ -87612,7 +95880,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); var lodash = require("lodash"); //------------------------------------------------------------------------------ @@ -87664,7 +95932,7 @@ function normalizeOptionValue(value) { consistent = Boolean(value.consistent); } } else { - multiline = true; + consistent = true; } return { multiline: multiline, minProperties: minProperties, consistent: consistent }; @@ -87716,7 +95984,9 @@ function areLineBreaksRequired(node, options, first, last) { } else { // is ImportDeclaration or ExportNamedDeclaration - objectProperties = node.specifiers; + objectProperties = node.specifiers.filter(function (s) { + return s.type === "ImportSpecifier" || s.type === "ExportSpecifier"; + }); } return objectProperties.length >= options.minProperties || options.multiline && objectProperties.length > 0 && first.loc.start.line !== last.loc.end.line; @@ -87728,13 +95998,17 @@ function areLineBreaksRequired(node, options, first, last) { module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent line breaks inside braces", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/object-curly-newline" }, + fixable: "whitespace", + schema: [{ oneOf: [OPTION_VALUE, { type: "object", @@ -87757,7 +96031,6 @@ module.exports = { /** * Reports a given node if it violated this rule. * @param {ASTNode} node - A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node. - * @param {{multiline: boolean, minProperties: number, consistent: boolean}} options - An option object. * @returns {void} */ function check(node) { @@ -87878,14 +96151,14 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],336:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],336:[function(require,module,exports){ /** * @fileoverview Disallows or enforces spaces inside of object literals. * @author Jamund Ferguson */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -87893,6 +96166,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing inside braces", category: "Stylistic Issues", @@ -88170,7 +96445,7 @@ module.exports = { } }; -},{"../ast-utils":115}],337:[function(require,module,exports){ +},{"../util/ast-utils":405}],337:[function(require,module,exports){ /** * @fileoverview Rule to enforce placing object properties on separate lines. * @author Vitor Balocco @@ -88184,6 +96459,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce placing object properties on separate lines", category: "Stylistic Issues", @@ -88208,8 +96485,7 @@ module.exports = { }, create: function create(context) { - var allowSameLine = context.options[0] && (Boolean(context.options[0].allowAllPropertiesOnSameLine) || Boolean(context.options[0].allowMultiplePropertiesPerLine) // Deprecated - ); + var allowSameLine = context.options[0] && (Boolean(context.options[0].allowAllPropertiesOnSameLine) || Boolean(context.options[0].allowMultiplePropertiesPerLine)); var errorMessage = allowSameLine ? "Object properties must go on a new line if they aren't all on the same line." : "Object properties must go on a new line."; var sourceCode = context.getSourceCode(); @@ -88281,13 +96557,15 @@ var OPTIONS = { //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow method and property shorthand syntax for object literals", category: "ECMAScript 6", @@ -88481,6 +96759,10 @@ module.exports = { var keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]); var keyPrefix = ""; + if (sourceCode.commentsExistBetween(lastKeyToken, node.value)) { + return null; + } + if (node.value.async) { keyPrefix += "async "; } @@ -88713,7 +96995,7 @@ module.exports = { } }; -},{"../ast-utils":115}],339:[function(require,module,exports){ +},{"../util/ast-utils":405}],339:[function(require,module,exports){ /** * @fileoverview Rule to check multiple var declarations per line * @author Alberto Rodríguez @@ -88726,6 +97008,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow newlines around variable declarations", category: "Stylistic Issues", @@ -88817,6 +97101,8 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce variables to be declared either together or separately in functions", category: "Stylistic Issues", @@ -88824,9 +97110,11 @@ module.exports = { url: "https://eslint.org/docs/rules/one-var" }, + fixable: "code", + schema: [{ oneOf: [{ - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] }, { type: "object", properties: { @@ -88834,13 +97122,13 @@ module.exports = { type: "boolean" }, var: { - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] }, let: { - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] }, const: { - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] } }, additionalProperties: false @@ -88848,10 +97136,10 @@ module.exports = { type: "object", properties: { initialized: { - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] }, uninitialized: { - enum: ["always", "never"] + enum: ["always", "never", "consecutive"] } }, additionalProperties: false @@ -88860,10 +97148,9 @@ module.exports = { }, create: function create(context) { - - var MODE_ALWAYS = "always", - MODE_NEVER = "never"; - + var MODE_ALWAYS = "always"; + var MODE_NEVER = "never"; + var MODE_CONSECUTIVE = "consecutive"; var mode = context.options[0] || MODE_ALWAYS; var options = {}; @@ -88875,19 +97162,19 @@ module.exports = { options.const = { uninitialized: mode, initialized: mode }; } else if ((typeof mode === "undefined" ? "undefined" : _typeof(mode)) === "object") { // options configuration is an object - if (mode.hasOwnProperty("separateRequires")) { + if (Object.prototype.hasOwnProperty.call(mode, "separateRequires")) { options.separateRequires = !!mode.separateRequires; } - if (mode.hasOwnProperty("var")) { + if (Object.prototype.hasOwnProperty.call(mode, "var")) { options.var = { uninitialized: mode.var, initialized: mode.var }; } - if (mode.hasOwnProperty("let")) { + if (Object.prototype.hasOwnProperty.call(mode, "let")) { options.let = { uninitialized: mode.let, initialized: mode.let }; } - if (mode.hasOwnProperty("const")) { + if (Object.prototype.hasOwnProperty.call(mode, "const")) { options.const = { uninitialized: mode.const, initialized: mode.const }; } - if (mode.hasOwnProperty("uninitialized")) { + if (Object.prototype.hasOwnProperty.call(mode, "uninitialized")) { if (!options.var) { options.var = {}; } @@ -88901,7 +97188,7 @@ module.exports = { options.let.uninitialized = mode.uninitialized; options.const.uninitialized = mode.uninitialized; } - if (mode.hasOwnProperty("initialized")) { + if (Object.prototype.hasOwnProperty.call(mode, "initialized")) { if (!options.var) { options.var = {}; } @@ -88917,6 +97204,8 @@ module.exports = { } } + var sourceCode = context.getSourceCode(); + //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- @@ -89075,6 +97364,238 @@ module.exports = { return true; } + /** + * Fixer to join VariableDeclaration's into a single declaration + * @param {VariableDeclarator[]} declarations The `VariableDeclaration` to join + * @returns {Function} The fixer function + */ + function joinDeclarations(declarations) { + var declaration = declarations[0]; + var body = Array.isArray(declaration.parent.parent.body) ? declaration.parent.parent.body : []; + var currentIndex = body.findIndex(function (node) { + return node.range[0] === declaration.parent.range[0]; + }); + var previousNode = body[currentIndex - 1]; + + return function (fixer) { + var type = sourceCode.getTokenBefore(declaration); + var prevSemi = sourceCode.getTokenBefore(type); + var res = []; + + if (previousNode && previousNode.kind === sourceCode.getText(type)) { + if (prevSemi.value === ";") { + res.push(fixer.replaceText(prevSemi, ",")); + } else { + res.push(fixer.insertTextAfter(prevSemi, ",")); + } + res.push(fixer.replaceText(type, "")); + } + + return res; + }; + } + + /** + * Fixer to split a VariableDeclaration into individual declarations + * @param {VariableDeclaration} declaration The `VariableDeclaration` to split + * @returns {Function} The fixer function + */ + function splitDeclarations(declaration) { + return function (fixer) { + return declaration.declarations.map(function (declarator) { + var tokenAfterDeclarator = sourceCode.getTokenAfter(declarator); + + if (tokenAfterDeclarator === null) { + return null; + } + + var afterComma = sourceCode.getTokenAfter(tokenAfterDeclarator, { includeComments: true }); + + if (tokenAfterDeclarator.value !== ",") { + return null; + } + + /* + * `var x,y` + * tokenAfterDeclarator ^^ afterComma + */ + if (afterComma.range[0] === tokenAfterDeclarator.range[1]) { + return fixer.replaceText(tokenAfterDeclarator, "; " + declaration.kind + " "); + } + + /* + * `var x, + * tokenAfterDeclarator ^ + * y` + * ^ afterComma + */ + if (afterComma.loc.start.line > tokenAfterDeclarator.loc.end.line || afterComma.type === "Line" || afterComma.type === "Block") { + var lastComment = afterComma; + + while (lastComment.type === "Line" || lastComment.type === "Block") { + lastComment = sourceCode.getTokenAfter(lastComment, { includeComments: true }); + } + + return fixer.replaceTextRange([tokenAfterDeclarator.range[0], lastComment.range[0]], ";\n" + sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0]) + "\n" + declaration.kind + " "); + } + + return fixer.replaceText(tokenAfterDeclarator, "; " + declaration.kind); + }).filter(function (x) { + return x; + }); + }; + } + + /** + * Checks a given VariableDeclaration node for errors. + * @param {ASTNode} node The VariableDeclaration node to check + * @returns {void} + * @private + */ + function checkVariableDeclaration(node) { + var parent = node.parent; + var type = node.kind; + + if (!options[type]) { + return; + } + + var declarations = node.declarations; + var declarationCounts = countDeclarations(declarations); + var mixedRequires = declarations.some(isRequire) && !declarations.every(isRequire); + + if (options[type].initialized === MODE_ALWAYS) { + if (options.separateRequires && mixedRequires) { + context.report({ + node: node, + message: "Split requires to be separated into a single block." + }); + } + } + + // consecutive + var nodeIndex = parent.body && parent.body.length > 0 && parent.body.indexOf(node) || 0; + + if (nodeIndex > 0) { + var previousNode = parent.body[nodeIndex - 1]; + var isPreviousNodeDeclaration = previousNode.type === "VariableDeclaration"; + var declarationsWithPrevious = declarations.concat(previousNode.declarations || []); + + if (isPreviousNodeDeclaration && previousNode.kind === type && !(declarationsWithPrevious.some(isRequire) && !declarationsWithPrevious.every(isRequire))) { + var previousDeclCounts = countDeclarations(previousNode.declarations); + + if (options[type].initialized === MODE_CONSECUTIVE && options[type].uninitialized === MODE_CONSECUTIVE) { + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } else if (options[type].initialized === MODE_CONSECUTIVE && declarationCounts.initialized > 0 && previousDeclCounts.initialized > 0) { + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement with initialized variables.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } else if (options[type].uninitialized === MODE_CONSECUTIVE && declarationCounts.uninitialized > 0 && previousDeclCounts.uninitialized > 0) { + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement with uninitialized variables.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } + } + } + + // always + if (!hasOnlyOneStatement(type, declarations)) { + if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) { + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } else { + if (options[type].initialized === MODE_ALWAYS && declarationCounts.initialized > 0) { + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement with initialized variables.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } + if (options[type].uninitialized === MODE_ALWAYS && declarationCounts.uninitialized > 0) { + if (node.parent.left === node && (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement")) { + return; + } + context.report({ + node: node, + message: "Combine this with the previous '{{type}}' statement with uninitialized variables.", + data: { + type: type + }, + fix: joinDeclarations(declarations) + }); + } + } + } + + // never + if (parent.type !== "ForStatement" || parent.init !== node) { + var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; + + if (totalDeclarations > 1) { + if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) { + + // both initialized and uninitialized + context.report({ + node: node, + message: "Split '{{type}}' declarations into multiple statements.", + data: { + type: type + }, + fix: splitDeclarations(node) + }); + } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) { + + // initialized + context.report({ + node: node, + message: "Split initialized '{{type}}' declarations into multiple statements.", + data: { + type: type + }, + fix: splitDeclarations(node) + }); + } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) { + + // uninitialized + context.report({ + node: node, + message: "Split uninitialized '{{type}}' declarations into multiple statements.", + data: { + type: type + }, + fix: splitDeclarations(node) + }); + } + } + } + } + //-------------------------------------------------------------------------- // Public API //-------------------------------------------------------------------------- @@ -89089,105 +97610,7 @@ module.exports = { ForInStatement: startBlock, ForOfStatement: startBlock, SwitchStatement: startBlock, - - VariableDeclaration: function VariableDeclaration(node) { - var parent = node.parent; - var type = node.kind; - - if (!options[type]) { - return; - } - - var declarations = node.declarations; - var declarationCounts = countDeclarations(declarations); - var mixedRequires = declarations.some(isRequire) && !declarations.every(isRequire); - - if (options[type].initialized === MODE_ALWAYS) { - if (options.separateRequires && mixedRequires) { - context.report({ - node: node, - message: "Split requires to be separated into a single block." - }); - } - } - - // always - if (!hasOnlyOneStatement(type, declarations)) { - if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) { - context.report({ - node: node, - message: "Combine this with the previous '{{type}}' statement.", - data: { - type: type - } - }); - } else { - if (options[type].initialized === MODE_ALWAYS) { - context.report({ - node: node, - message: "Combine this with the previous '{{type}}' statement with initialized variables.", - data: { - type: type - } - }); - } - if (options[type].uninitialized === MODE_ALWAYS) { - if (node.parent.left === node && (node.parent.type === "ForInStatement" || node.parent.type === "ForOfStatement")) { - return; - } - context.report({ - node: node, - message: "Combine this with the previous '{{type}}' statement with uninitialized variables.", - data: { - type: type - } - }); - } - } - } - - // never - if (parent.type !== "ForStatement" || parent.init !== node) { - var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; - - if (totalDeclarations > 1) { - - if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) { - - // both initialized and uninitialized - context.report({ - node: node, - message: "Split '{{type}}' declarations into multiple statements.", - data: { - type: type - } - }); - } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) { - - // initialized - context.report({ - node: node, - message: "Split initialized '{{type}}' declarations into multiple statements.", - data: { - type: type - } - }); - } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) { - - // uninitialized - context.report({ - node: node, - message: "Split uninitialized '{{type}}' declarations into multiple statements.", - data: { - type: type - } - }); - } - } - } - }, - - + VariableDeclaration: checkVariableDeclaration, "ForStatement:exit": endBlock, "ForOfStatement:exit": endBlock, "ForInStatement:exit": endBlock, @@ -89212,7 +97635,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -89292,6 +97715,8 @@ function canBeFixed(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow assignment operator shorthand where possible", category: "Stylistic Issues", @@ -89405,7 +97830,7 @@ module.exports = { } }; -},{"../ast-utils":115}],342:[function(require,module,exports){ +},{"../util/ast-utils":405}],342:[function(require,module,exports){ /** * @fileoverview Operator linebreak - enforces operator linebreak style of two types: after and before * @author Benoît Zugmeyer @@ -89417,7 +97842,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -89425,6 +97850,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent linebreak style for operators", category: "Stylistic Issues", @@ -89651,7 +98078,7 @@ module.exports = { } }; -},{"../ast-utils":115}],343:[function(require,module,exports){ +},{"../util/ast-utils":405}],343:[function(require,module,exports){ /** * @fileoverview A rule to ensure blank lines within blocks. * @author Mathias Schreck @@ -89665,6 +98092,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow padding within blocks", category: "Stylistic Issues", @@ -89707,13 +98136,13 @@ module.exports = { options.switches = shouldHavePadding; options.classes = shouldHavePadding; } else { - if (config.hasOwnProperty("blocks")) { + if (Object.prototype.hasOwnProperty.call(config, "blocks")) { options.blocks = config.blocks === "always"; } - if (config.hasOwnProperty("switches")) { + if (Object.prototype.hasOwnProperty.call(config, "switches")) { options.switches = config.switches === "always"; } - if (config.hasOwnProperty("classes")) { + if (Object.prototype.hasOwnProperty.call(config, "classes")) { options.classes = config.classes === "always"; } } @@ -89876,7 +98305,7 @@ module.exports = { var rule = {}; - if (options.hasOwnProperty("switches")) { + if (Object.prototype.hasOwnProperty.call(options, "switches")) { rule.SwitchStatement = function (node) { if (node.cases.length === 0) { return; @@ -89885,7 +98314,7 @@ module.exports = { }; } - if (options.hasOwnProperty("blocks")) { + if (Object.prototype.hasOwnProperty.call(options, "blocks")) { rule.BlockStatement = function (node) { if (node.body.length === 0) { return; @@ -89894,7 +98323,7 @@ module.exports = { }; } - if (options.hasOwnProperty("classes")) { + if (Object.prototype.hasOwnProperty.call(options, "classes")) { rule.ClassBody = function (node) { if (node.body.length === 0) { return; @@ -89923,7 +98352,7 @@ var _templateObject = _taggedTemplateLiteral(["^(s*?", ")s*", "(s*;?)$"], ["^(\\ function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -89949,6 +98378,36 @@ function newKeywordTester(keyword) { }; } +/** + * Creates tester which check if a node starts with specific keyword and spans a single line. + * + * @param {string} keyword The keyword to test. + * @returns {Object} the created tester. + * @private + */ +function newSinglelineKeywordTester(keyword) { + return { + test: function test(node, sourceCode) { + return node.loc.start.line === node.loc.end.line && sourceCode.getFirstToken(node).value === keyword; + } + }; +} + +/** + * Creates tester which check if a node starts with specific keyword and spans multiple lines. + * + * @param {string} keyword The keyword to test. + * @returns {Object} the created tester. + * @private + */ +function newMultilineKeywordTester(keyword) { + return { + test: function test(node, sourceCode) { + return node.loc.start.line !== node.loc.end.line && sourceCode.getFirstToken(node).value === keyword; + } + }; +} + /** * Creates tester which check if a node is specific type. * @@ -90257,6 +98716,9 @@ var StatementTypes = { return node.type === "ExpressionStatement" && !isDirectivePrologue(node, sourceCode); } }, + iife: { + test: isIIFEStatement + }, "multiline-block-like": { test: function test(node, sourceCode) { return node.loc.start.line !== node.loc.end.line && isBlockLikeStatement(sourceCode, node); @@ -90268,8 +98730,16 @@ var StatementTypes = { } }, + "multiline-const": newMultilineKeywordTester("const"), + "multiline-let": newMultilineKeywordTester("let"), + "multiline-var": newMultilineKeywordTester("var"), + "singleline-const": newSinglelineKeywordTester("const"), + "singleline-let": newSinglelineKeywordTester("let"), + "singleline-var": newSinglelineKeywordTester("var"), + block: newNodeTypeTester("BlockStatement"), empty: newNodeTypeTester("EmptyStatement"), + function: newNodeTypeTester("FunctionDeclaration"), break: newKeywordTester("break"), case: newKeywordTester("case"), @@ -90281,7 +98751,6 @@ var StatementTypes = { do: newKeywordTester("do"), export: newKeywordTester("export"), for: newKeywordTester("for"), - function: newKeywordTester("function"), if: newKeywordTester("if"), import: newKeywordTester("import"), let: newKeywordTester("let"), @@ -90300,13 +98769,17 @@ var StatementTypes = { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow padding lines between statements", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/padding-line-between-statements" }, + fixable: "whitespace", + schema: { definitions: { paddingType: { @@ -90373,13 +98846,15 @@ module.exports = { * @private */ function match(node, type) { - while (node.type === "LabeledStatement") { - node = node.body; + var innerStatementNode = node; + + while (innerStatementNode.type === "LabeledStatement") { + innerStatementNode = innerStatementNode.body; } if (Array.isArray(type)) { - return type.some(match.bind(null, node)); + return type.some(match.bind(null, innerStatementNode)); } - return StatementTypes[type].test(node, sourceCode); + return StatementTypes[type].test(innerStatementNode, sourceCode); } /** @@ -90487,7 +98962,7 @@ module.exports = { } }; -},{"../ast-utils":115}],345:[function(require,module,exports){ +},{"../util/ast-utils":405}],345:[function(require,module,exports){ /** * @fileoverview A rule to suggest using arrow functions as callbacks. * @author Toru Nagashima @@ -90555,9 +99030,10 @@ function getVariableOfArguments(scope) { */ function getCallbackInfo(node) { var retv = { isCallback: false, isLexicalThis: false }; + var currentNode = node; var parent = node.parent; - while (node) { + while (currentNode) { switch (parent.type) { // Checks parents recursively. @@ -90568,7 +99044,7 @@ function getCallbackInfo(node) { // Checks whether the parent node is `.bind(this)` call. case "MemberExpression": - if (parent.object === node && !parent.property.computed && parent.property.type === "Identifier" && parent.property.name === "bind" && parent.parent.type === "CallExpression" && parent.parent.callee === parent) { + if (parent.object === currentNode && !parent.property.computed && parent.property.type === "Identifier" && parent.property.name === "bind" && parent.parent.type === "CallExpression" && parent.parent.callee === parent) { retv.isLexicalThis = parent.parent.arguments.length === 1 && parent.parent.arguments[0].type === "ThisExpression"; parent = parent.parent; } else { @@ -90579,7 +99055,7 @@ function getCallbackInfo(node) { // Checks whether the node is a callback. case "CallExpression": case "NewExpression": - if (parent.callee !== node) { + if (parent.callee !== currentNode) { retv.isCallback = true; } return retv; @@ -90588,7 +99064,7 @@ function getCallbackInfo(node) { return retv; } - node = parent; + currentNode = parent; parent = parent.parent; } @@ -90617,6 +99093,8 @@ function hasDuplicateParams(paramsList) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require using arrow functions for callbacks", category: "ECMAScript 6", @@ -90792,6 +99270,10 @@ module.exports = { "use strict"; +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var astUtils = require("../util/ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -90800,15 +99282,6 @@ var PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestPr var DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; var DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; -/** - * Adds multiple items to the tail of an array. - * - * @param {any[]} array - A destination to add. - * @param {any[]} values - Items to be added. - * @returns {void} - */ -var pushAll = Function.apply.bind(Array.prototype.push); - /** * Checks whether a given node is located at `ForStatement.init` or not. * @@ -90835,6 +99308,107 @@ function canBecomeVariableDeclaration(identifier) { return node.type === "VariableDeclarator" || node.type === "AssignmentExpression" && node.parent.type === "ExpressionStatement" && DECLARATION_HOST_TYPE.test(node.parent.parent.type); } +/** + * Checks if an property or element is from outer scope or function parameters + * in destructing pattern. + * + * @param {string} name - A variable name to be checked. + * @param {eslint-scope.Scope} initScope - A scope to start find. + * @returns {boolean} Indicates if the variable is from outer scope or function parameters. + */ +function isOuterVariableInDestructing(name, initScope) { + + if (initScope.through.find(function (ref) { + return ref.resolved && ref.resolved.name === name; + })) { + return true; + } + + var variable = astUtils.getVariableByName(initScope, name); + + if (variable !== null) { + return variable.defs.some(function (def) { + return def.type === "Parameter"; + }); + } + + return false; +} + +/** + * Gets the VariableDeclarator/AssignmentExpression node that a given reference + * belongs to. + * This is used to detect a mix of reassigned and never reassigned in a + * destructuring. + * + * @param {eslint-scope.Reference} reference - A reference to get. + * @returns {ASTNode|null} A VariableDeclarator/AssignmentExpression node or + * null. + */ +function getDestructuringHost(reference) { + if (!reference.isWrite()) { + return null; + } + var node = reference.identifier.parent; + + while (PATTERN_TYPE.test(node.type)) { + node = node.parent; + } + + if (!DESTRUCTURING_HOST_TYPE.test(node.type)) { + return null; + } + return node; +} + +/** + * Determines if a destructuring assignment node contains + * any MemberExpression nodes. This is used to determine if a + * variable that is only written once using destructuring can be + * safely converted into a const declaration. + * @param {ASTNode} node The ObjectPattern or ArrayPattern node to check. + * @returns {boolean} True if the destructuring pattern contains + * a MemberExpression, false if not. + */ +function hasMemberExpressionAssignment(node) { + switch (node.type) { + case "ObjectPattern": + return node.properties.some(function (prop) { + if (prop) { + + /* + * Spread elements have an argument property while + * others have a value property. Because different + * parsers use different node types for spread elements, + * we just check if there is an argument property. + */ + return hasMemberExpressionAssignment(prop.argument || prop.value); + } + + return false; + }); + + case "ArrayPattern": + return node.elements.some(function (element) { + if (element) { + return hasMemberExpressionAssignment(element); + } + + return false; + }); + + case "AssignmentPattern": + return hasMemberExpressionAssignment(node.left); + + case "MemberExpression": + return true; + + // no default + } + + return false; +} + /** * Gets an identifier node of a given variable. * @@ -90879,6 +99453,43 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { if (isReassigned) { return null; } + + var destructuringHost = getDestructuringHost(reference); + + if (destructuringHost !== null && destructuringHost.left !== void 0) { + var leftNode = destructuringHost.left; + var hasOuterVariables = false, + hasNonIdentifiers = false; + + if (leftNode.type === "ObjectPattern") { + var properties = leftNode.properties; + + hasOuterVariables = properties.filter(function (prop) { + return prop.value; + }).map(function (prop) { + return prop.value.name; + }).some(function (name) { + return isOuterVariableInDestructing(name, variable.scope); + }); + + hasNonIdentifiers = hasMemberExpressionAssignment(leftNode); + } else if (leftNode.type === "ArrayPattern") { + var elements = leftNode.elements; + + hasOuterVariables = elements.map(function (element) { + return element && element.name; + }).some(function (name) { + return isOuterVariableInDestructing(name, variable.scope); + }); + + hasNonIdentifiers = hasMemberExpressionAssignment(leftNode); + } + + if (hasOuterVariables || hasNonIdentifiers) { + return null; + } + } + writer = reference; } else if (reference.isRead() && writer === null) { if (ignoreReadBeforeAssign) { @@ -90897,38 +99508,14 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { if (!shouldBeConst) { return null; } + if (isReadBeforeInit) { return variable.defs[0].name; } + return writer.identifier; } -/** - * Gets the VariableDeclarator/AssignmentExpression node that a given reference - * belongs to. - * This is used to detect a mix of reassigned and never reassigned in a - * destructuring. - * - * @param {eslint-scope.Reference} reference - A reference to get. - * @returns {ASTNode|null} A VariableDeclarator/AssignmentExpression node or - * null. - */ -function getDestructuringHost(reference) { - if (!reference.isWrite()) { - return null; - } - var node = reference.identifier.parent; - - while (PATTERN_TYPE.test(node.type)) { - node = node.parent; - } - - if (!DESTRUCTURING_HOST_TYPE.test(node.type)) { - return null; - } - return node; -} - /** * Groups by the VariableDeclarator/AssignmentExpression node that each * reference of given variables belongs to. @@ -91002,6 +99589,8 @@ function findUp(node, type, shouldStop) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `const` declarations for variables that are never reassigned after declared", category: "ECMAScript 6", @@ -91024,9 +99613,11 @@ module.exports = { create: function create(context) { var options = context.options[0] || {}; var sourceCode = context.getSourceCode(); - var checkingMixedDestructuring = options.destructuring !== "all"; + var shouldMatchAnyDestructuredVariable = options.destructuring !== "all"; var ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true; var variables = []; + var reportCount = 0; + var name = ""; /** * Reports given identifier nodes if all of the nodes should be declared @@ -91045,29 +99636,71 @@ module.exports = { function checkGroup(nodes) { var nodesToReport = nodes.filter(Boolean); - if (nodes.length && (checkingMixedDestructuring || nodesToReport.length === nodes.length)) { + if (nodes.length && (shouldMatchAnyDestructuredVariable || nodesToReport.length === nodes.length)) { var varDeclParent = findUp(nodes[0], "VariableDeclaration", function (parentNode) { return parentNode.type.endsWith("Statement"); }); - var shouldFix = varDeclParent && + var isVarDecParentNull = varDeclParent === null; - /* - * If there are multiple variable declarations, like {let a = 1, b = 2}, then - * do not attempt to fix if one of the declarations should be `const`. It's - * too hard to know how the developer would want to automatically resolve the issue. - */ - varDeclParent.declarations.length === 1 && ( + if (!isVarDecParentNull && varDeclParent.declarations.length > 0) { + var firstDeclaration = varDeclParent.declarations[0]; + + if (firstDeclaration.init) { + var firstDecParent = firstDeclaration.init.parent; + + /* + * First we check the declaration type and then depending on + * if the type is a "VariableDeclarator" or its an "ObjectPattern" + * we compare the name from the first identifier, if the names are different + * we assign the new name and reset the count of reportCount and nodeCount in + * order to check each block for the number of reported errors and base our fix + * based on comparing nodes.length and nodesToReport.length. + */ + + if (firstDecParent.type === "VariableDeclarator") { + + if (firstDecParent.id.name !== name) { + name = firstDecParent.id.name; + reportCount = 0; + } + + if (firstDecParent.id.type === "ObjectPattern") { + if (firstDecParent.init.name !== name) { + name = firstDecParent.init.name; + reportCount = 0; + } + } + } + } + } + + var shouldFix = varDeclParent && ( // Don't do a fix unless the variable is initialized (or it's in a for-in or for-of loop) varDeclParent.parent.type === "ForInStatement" || varDeclParent.parent.type === "ForOfStatement" || varDeclParent.declarations[0].init) && /* - * If options.destucturing is "all", then this warning will not occur unless + * If options.destructuring is "all", then this warning will not occur unless * every assignment in the destructuring should be const. In that case, it's safe * to apply the fix. */ nodesToReport.length === nodes.length; + if (!isVarDecParentNull && varDeclParent.declarations && varDeclParent.declarations.length !== 1) { + + if (varDeclParent && varDeclParent.declarations && varDeclParent.declarations.length >= 1) { + + /* + * Add nodesToReport.length to a count, then comparing the count to the length + * of the declarations in the current block. + */ + + reportCount += nodesToReport.length; + + shouldFix = shouldFix && reportCount === varDeclParent.declarations.length; + } + } + nodesToReport.forEach(function (node) { context.report({ node: node, @@ -91087,14 +99720,14 @@ module.exports = { }, VariableDeclaration: function VariableDeclaration(node) { if (node.kind === "let" && !isInitOfForStatement(node)) { - pushAll(variables, context.getDeclaredVariables(node)); + variables.push.apply(variables, _toConsumableArray(context.getDeclaredVariables(node))); } } }; } }; -},{}],347:[function(require,module,exports){ +},{"../util/ast-utils":405}],347:[function(require,module,exports){ /** * @fileoverview Prefer destructuring from arrays and objects * @author Alex LaFroscia @@ -91107,12 +99740,15 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require destructuring from arrays and/or objects", category: "ECMAScript 6", recommended: false, url: "https://eslint.org/docs/rules/prefer-destructuring" }, + schema: [{ /* @@ -91342,6 +99978,8 @@ function isParseInt(calleeNode) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow `parseInt()` and `Number.parseInt()` in favor of binary, octal, and hexadecimal literals", category: "ECMAScript 6", @@ -91350,7 +99988,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -91413,13 +100050,455 @@ module.exports = { }; },{}],349:[function(require,module,exports){ +/** + * @fileoverview Prefers object spread property over Object.assign + * @author Sharmila Jesupaul + * See LICENSE file in root directory for full license. + */ + +"use strict"; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var _require = require("eslint-utils"), + CALL = _require.CALL, + ReferenceTracker = _require.ReferenceTracker; + +var _require2 = require("../util/ast-utils"), + isCommaToken = _require2.isCommaToken, + isOpeningParenToken = _require2.isOpeningParenToken, + isClosingParenToken = _require2.isClosingParenToken, + isParenthesised = _require2.isParenthesised; + +var ANY_SPACE = /\s/; + +/** + * Helper that checks if the Object.assign call has array spread + * @param {ASTNode} node - The node that the rule warns on + * @returns {boolean} - Returns true if the Object.assign call has array spread + */ +function hasArraySpread(node) { + return node.arguments.some(function (arg) { + return arg.type === "SpreadElement"; + }); +} + +/** + * Helper that checks if the node needs parentheses to be valid JS. + * The default is to wrap the node in parentheses to avoid parsing errors. + * @param {ASTNode} node - The node that the rule warns on + * @param {Object} sourceCode - in context sourcecode object + * @returns {boolean} - Returns true if the node needs parentheses + */ +function needsParens(node, sourceCode) { + var parent = node.parent; + + switch (parent.type) { + case "VariableDeclarator": + case "ArrayExpression": + case "ReturnStatement": + case "CallExpression": + case "Property": + return false; + case "AssignmentExpression": + return parent.left === node && !isParenthesised(sourceCode, node); + default: + return !isParenthesised(sourceCode, node); + } +} + +/** + * Determines if an argument needs parentheses. The default is to not add parens. + * @param {ASTNode} node - The node to be checked. + * @param {Object} sourceCode - in context sourcecode object + * @returns {boolean} True if the node needs parentheses + */ +function argNeedsParens(node, sourceCode) { + switch (node.type) { + case "AssignmentExpression": + case "ArrowFunctionExpression": + case "ConditionalExpression": + return !isParenthesised(sourceCode, node); + default: + return false; + } +} + +/** + * Get the parenthesis tokens of a given ObjectExpression node. + * This incldues the braces of the object literal and enclosing parentheses. + * @param {ASTNode} node The node to get. + * @param {Token} leftArgumentListParen The opening paren token of the argument list. + * @param {SourceCode} sourceCode The source code object to get tokens. + * @returns {Token[]} The parenthesis tokens of the node. This is sorted by the location. + */ +function getParenTokens(node, leftArgumentListParen, sourceCode) { + var parens = [sourceCode.getFirstToken(node), sourceCode.getLastToken(node)]; + var leftNext = sourceCode.getTokenBefore(node); + var rightNext = sourceCode.getTokenAfter(node); + + // Note: don't include the parens of the argument list. + while (leftNext && rightNext && leftNext.range[0] > leftArgumentListParen.range[0] && isOpeningParenToken(leftNext) && isClosingParenToken(rightNext)) { + parens.push(leftNext, rightNext); + leftNext = sourceCode.getTokenBefore(leftNext); + rightNext = sourceCode.getTokenAfter(rightNext); + } + + return parens.sort(function (a, b) { + return a.range[0] - b.range[0]; + }); +} + +/** + * Get the range of a given token and around whitespaces. + * @param {Token} token The token to get range. + * @param {SourceCode} sourceCode The source code object to get tokens. + * @returns {number} The end of the range of the token and around whitespaces. + */ +function getStartWithSpaces(token, sourceCode) { + var text = sourceCode.text; + var start = token.range[0]; + + // If the previous token is a line comment then skip this step to avoid commenting this token out. + { + var prevToken = sourceCode.getTokenBefore(token, { includeComments: true }); + + if (prevToken && prevToken.type === "Line") { + return start; + } + } + + // Detect spaces before the token. + while (ANY_SPACE.test(text[start - 1] || "")) { + start -= 1; + } + + return start; +} + +/** + * Get the range of a given token and around whitespaces. + * @param {Token} token The token to get range. + * @param {SourceCode} sourceCode The source code object to get tokens. + * @returns {number} The start of the range of the token and around whitespaces. + */ +function getEndWithSpaces(token, sourceCode) { + var text = sourceCode.text; + var end = token.range[1]; + + // Detect spaces after the token. + while (ANY_SPACE.test(text[end] || "")) { + end += 1; + } + + return end; +} + +/** + * Autofixes the Object.assign call to use an object spread instead. + * @param {ASTNode|null} node - The node that the rule warns on, i.e. the Object.assign call + * @param {string} sourceCode - sourceCode of the Object.assign call + * @returns {Function} autofixer - replaces the Object.assign with a spread object. + */ +function defineFixer(node, sourceCode) { + return (/*#__PURE__*/regeneratorRuntime.mark(function _callee(fixer) { + var leftParen, rightParen, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, argNode, innerParens, left, right, maybeTrailingComma, maybeArgumentComma, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, innerParen, leftRange, rightRange; + + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + leftParen = sourceCode.getTokenAfter(node.callee, isOpeningParenToken); + rightParen = sourceCode.getLastToken(node); + + // Remove the callee `Object.assign` + + _context.next = 4; + return fixer.remove(node.callee); + + case 4: + if (!needsParens(node, sourceCode)) { + _context.next = 11; + break; + } + + _context.next = 7; + return fixer.replaceText(leftParen, "({"); + + case 7: + _context.next = 9; + return fixer.replaceText(rightParen, "})"); + + case 9: + _context.next = 15; + break; + + case 11: + _context.next = 13; + return fixer.replaceText(leftParen, "{"); + + case 13: + _context.next = 15; + return fixer.replaceText(rightParen, "}"); + + case 15: + + // Process arguments. + _iteratorNormalCompletion = true; + _didIteratorError = false; + _iteratorError = undefined; + _context.prev = 18; + _iterator = node.arguments[Symbol.iterator](); + + case 20: + if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { + _context.next = 77; + break; + } + + argNode = _step.value; + innerParens = getParenTokens(argNode, leftParen, sourceCode); + left = innerParens.shift(); + right = innerParens.pop(); + + if (!(argNode.type === "ObjectExpression")) { + _context.next = 65; + break; + } + + maybeTrailingComma = sourceCode.getLastToken(argNode, 1); + maybeArgumentComma = sourceCode.getTokenAfter(right); + + /* + * Make bare this object literal. + * And remove spaces inside of the braces for better formatting. + */ + + _iteratorNormalCompletion2 = true; + _didIteratorError2 = false; + _iteratorError2 = undefined; + _context.prev = 31; + _iterator2 = innerParens[Symbol.iterator](); + + case 33: + if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) { + _context.next = 40; + break; + } + + innerParen = _step2.value; + _context.next = 37; + return fixer.remove(innerParen); + + case 37: + _iteratorNormalCompletion2 = true; + _context.next = 33; + break; + + case 40: + _context.next = 46; + break; + + case 42: + _context.prev = 42; + _context.t0 = _context["catch"](31); + _didIteratorError2 = true; + _iteratorError2 = _context.t0; + + case 46: + _context.prev = 46; + _context.prev = 47; + + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + + case 49: + _context.prev = 49; + + if (!_didIteratorError2) { + _context.next = 52; + break; + } + + throw _iteratorError2; + + case 52: + return _context.finish(49); + + case 53: + return _context.finish(46); + + case 54: + leftRange = [left.range[0], getEndWithSpaces(left, sourceCode)]; + rightRange = [Math.max(getStartWithSpaces(right, sourceCode), leftRange[1]), // Ensure ranges don't overlap + right.range[1]]; + _context.next = 58; + return fixer.removeRange(leftRange); + + case 58: + _context.next = 60; + return fixer.removeRange(rightRange); + + case 60: + if (!((argNode.properties.length === 0 || isCommaToken(maybeTrailingComma)) && isCommaToken(maybeArgumentComma))) { + _context.next = 63; + break; + } + + _context.next = 63; + return fixer.remove(maybeArgumentComma); + + case 63: + _context.next = 74; + break; + + case 65: + if (!argNeedsParens(argNode, sourceCode)) { + _context.next = 72; + break; + } + + _context.next = 68; + return fixer.insertTextBefore(left, "...("); + + case 68: + _context.next = 70; + return fixer.insertTextAfter(right, ")"); + + case 70: + _context.next = 74; + break; + + case 72: + _context.next = 74; + return fixer.insertTextBefore(left, "..."); + + case 74: + _iteratorNormalCompletion = true; + _context.next = 20; + break; + + case 77: + _context.next = 83; + break; + + case 79: + _context.prev = 79; + _context.t1 = _context["catch"](18); + _didIteratorError = true; + _iteratorError = _context.t1; + + case 83: + _context.prev = 83; + _context.prev = 84; + + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + + case 86: + _context.prev = 86; + + if (!_didIteratorError) { + _context.next = 89; + break; + } + + throw _iteratorError; + + case 89: + return _context.finish(86); + + case 90: + return _context.finish(83); + + case 91: + case "end": + return _context.stop(); + } + } + }, _callee, this, [[18, 79, 83, 91], [31, 42, 46, 54], [47,, 49, 53], [84,, 86, 90]]); + }) + ); +} + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "disallow using Object.assign with an object literal as the first argument and prefer the use of object spread instead.", + category: "Stylistic Issues", + recommended: false, + url: "https://eslint.org/docs/rules/prefer-object-spread" + }, + + schema: [], + fixable: "code", + + messages: { + useSpreadMessage: "Use an object spread instead of `Object.assign` eg: `{ ...foo }`", + useLiteralMessage: "Use an object literal instead of `Object.assign`. eg: `{ foo: bar }`" + } + }, + + create: function create(context) { + var sourceCode = context.getSourceCode(); + + return { + Program: function Program() { + var scope = context.getScope(); + var tracker = new ReferenceTracker(scope); + var trackMap = { + Object: { + assign: _defineProperty({}, CALL, true) + } + }; + + // Iterate all calls of `Object.assign` (only of the global variable `Object`). + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = tracker.iterateGlobalReferences(trackMap)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var node = _step3.value.node; + + if (node.arguments.length >= 1 && node.arguments[0].type === "ObjectExpression" && !hasArraySpread(node)) { + var messageId = node.arguments.length === 1 ? "useLiteralMessage" : "useSpreadMessage"; + var fix = defineFixer(node, sourceCode); + + context.report({ node: node, messageId: messageId, fix: fix }); + } + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + } + }; + } +}; + +},{"../util/ast-utils":405,"eslint-utils":68}],350:[function(require,module,exports){ /** * @fileoverview restrict values that can be used as Promise rejection reasons * @author Teddy Katz */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -91427,13 +100506,17 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "require using Error objects as Promise rejection reasons", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/prefer-promise-reject-errors" }, + fixable: null, + schema: [{ type: "object", properties: { @@ -91536,7 +100619,7 @@ module.exports = { } }; -},{"../ast-utils":115}],350:[function(require,module,exports){ +},{"../util/ast-utils":405}],351:[function(require,module,exports){ /** * @fileoverview Rule to suggest using "Reflect" api over Function/Object methods * @author Keith Cirkel @@ -91550,16 +100633,19 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `Reflect` methods where applicable", category: "ECMAScript 6", recommended: false, - replacedBy: [], url: "https://eslint.org/docs/rules/prefer-reflect" }, deprecated: true, + replacedBy: [], + schema: [{ type: "object", properties: { @@ -91624,7 +100710,7 @@ module.exports = { CallExpression: function CallExpression(node) { var methodName = (node.callee.property || {}).name; var isReflectCall = (node.callee.object || {}).name === "Reflect"; - var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); + var hasReflectSubsitute = Object.prototype.hasOwnProperty.call(reflectSubsitutes, methodName); var userConfiguredException = exceptions.indexOf(methodName) !== -1; if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) { @@ -91644,7 +100730,7 @@ module.exports = { } }; -},{}],351:[function(require,module,exports){ +},{}],352:[function(require,module,exports){ /** * @fileoverview Rule to * @author Toru Nagashima @@ -91706,6 +100792,8 @@ function isNotNormalMemberAccess(reference) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require rest parameters instead of `arguments`", category: "ECMAScript 6", @@ -91752,7 +100840,7 @@ module.exports = { } }; -},{}],352:[function(require,module,exports){ +},{}],353:[function(require,module,exports){ /** * @fileoverview A rule to suggest using of the spread operator instead of `.apply()`. * @author Toru Nagashima @@ -91760,7 +100848,7 @@ module.exports = { "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -91795,6 +100883,8 @@ function isValidThisArg(expectedThis, thisArg, context) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require spread operators instead of `.apply()`", category: "ECMAScript 6", @@ -91803,7 +100893,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -91844,7 +100933,7 @@ module.exports = { } }; -},{"../ast-utils":115}],353:[function(require,module,exports){ +},{"../util/ast-utils":405}],354:[function(require,module,exports){ /** * @fileoverview A rule to suggest using template literals instead of string concatenation. * @author Toru Nagashima @@ -91856,7 +100945,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -91877,10 +100966,51 @@ function isConcatenation(node) { * @returns {ASTNode} the top binary expression node in parents of a given node. */ function getTopConcatBinaryExpression(node) { - while (isConcatenation(node.parent)) { - node = node.parent; + var currentNode = node; + + while (isConcatenation(currentNode.parent)) { + currentNode = currentNode.parent; } - return node; + return currentNode; +} + +/** + * Determines whether a given node is a octal escape sequence + * @param {ASTNode} node A node to check + * @returns {boolean} `true` if the node is an octal escape sequence + */ +function isOctalEscapeSequence(node) { + + // No need to check TemplateLiterals – would throw error with octal escape + var isStringLiteral = node.type === "Literal" && typeof node.value === "string"; + + if (!isStringLiteral) { + return false; + } + + var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-7]{1,3})/); + + if (match) { + + // \0 is actually not considered an octal + if (match[2] !== "0" || typeof match[3] !== "undefined") { + return true; + } + } + return false; +} + +/** + * Checks whether or not a node contains a octal escape sequence + * @param {ASTNode} node A node to check + * @returns {boolean} `true` if the node contains an octal escape sequence + */ +function hasOctalEscapeSequence(node) { + if (isConcatenation(node)) { + return hasOctalEscapeSequence(node.left) || hasOctalEscapeSequence(node.right); + } + + return isOctalEscapeSequence(node); } /** @@ -91947,6 +101077,8 @@ function endsWithTemplateCurly(node) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require template literals instead of string concatenation", category: "ECMAScript 6", @@ -91955,7 +101087,6 @@ module.exports = { }, schema: [], - fixable: "code" }, @@ -92040,6 +101171,22 @@ module.exports = { return "`${" + (textBeforeNode || "") + sourceCode.getText(currentNode) + (textAfterNode || "") + "}`"; } + /** + * Returns a fixer object that converts a non-string binary expression to a template literal + * @param {SourceCodeFixer} fixer The fixer object + * @param {ASTNode} node A node that should be converted to a template literal + * @returns {Object} A fix for this binary expression + */ + function fixNonStringBinaryExpression(fixer, node) { + var topBinaryExpr = getTopConcatBinaryExpression(node.parent); + + if (hasOctalEscapeSequence(topBinaryExpr)) { + return null; + } + + return fixer.replaceText(topBinaryExpr, getTemplateLiteral(topBinaryExpr, null, null)); + } + /** * Reports if a given node is string concatenation with non string literals. * @@ -92064,7 +101211,7 @@ module.exports = { node: topBinaryExpr, message: "Unexpected string concatenation.", fix: function fix(fixer) { - return fixer.replaceText(topBinaryExpr, getTemplateLiteral(topBinaryExpr, null, null)); + return fixNonStringBinaryExpression(fixer, node); } }); } @@ -92082,7 +101229,7 @@ module.exports = { } }; -},{"../ast-utils":115}],354:[function(require,module,exports){ +},{"../util/ast-utils":405}],355:[function(require,module,exports){ /** * @fileoverview Rule to flag non-quoted property names in object literals. * @author Mathias Bynens @@ -92102,6 +101249,8 @@ var espree = require("espree"), module.exports = { meta: { + type: "suggestion", + docs: { description: "require quotes around object literal property names", category: "Stylistic Issues", @@ -92384,7 +101533,7 @@ module.exports = { } }; -},{"../util/keywords":405,"espree":"espree"}],355:[function(require,module,exports){ +},{"../util/keywords":409,"espree":"espree"}],356:[function(require,module,exports){ /** * @fileoverview A rule to choose between single and double quote marks * @author Matt DuVall , Brandon Payton @@ -92400,7 +101549,7 @@ var _templateObject = _taggedTemplateLiteral(["(^|[^\\])(\\\\)*[", "]"], ["(^|[^ function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Constants @@ -92465,6 +101614,8 @@ var AVOID_ESCAPE = "avoid-escape"; module.exports = { meta: { + type: "layout", + docs: { description: "enforce the consistent use of either backticks, double, or single quotes", category: "Stylistic Issues", @@ -92515,6 +101666,7 @@ module.exports = { * * - `
` ... If the literal is an attribute value, the parent of the literal is `JSXAttribute`. * - `
foo
` ... If the literal is a text content, the parent of the literal is `JSXElement`. + * - `<>foo` ... If the literal is a text content, the parent of the literal is `JSXFragment`. * * In particular, this function returns `false` in the following cases: * @@ -92529,7 +101681,7 @@ module.exports = { * @private */ function isJSXLiteral(node) { - return node.parent.type === "JSXAttribute" || node.parent.type === "JSXElement"; + return node.parent.type === "JSXAttribute" || node.parent.type === "JSXElement" || node.parent.type === "JSXFragment"; } /** @@ -92604,6 +101756,34 @@ module.exports = { } } + /** + * Checks whether or not a given TemplateLiteral node is actually using any of the special features provided by template literal strings. + * @param {ASTNode} node - A TemplateLiteral node to check. + * @returns {boolean} Whether or not the TemplateLiteral node is using any of the special features provided by template literal strings. + * @private + */ + function isUsingFeatureOfTemplateLiteral(node) { + var hasTag = node.parent.type === "TaggedTemplateExpression" && node === node.parent.quasi; + + if (hasTag) { + return true; + } + + var hasStringInterpolation = node.expressions.length > 0; + + if (hasStringInterpolation) { + return true; + } + + var isMultilineString = node.quasis.length >= 1 && UNESCAPED_LINEBREAK_PATTERN.test(node.quasis[0].value.raw); + + if (isMultilineString) { + return true; + } + + return false; + } + return { Literal: function Literal(node) { var val = node.value, @@ -92632,41 +101812,36 @@ module.exports = { }, TemplateLiteral: function TemplateLiteral(node) { - // If backticks are expected or it's a tagged template, then this shouldn't throw an errors - if (allowTemplateLiterals || quoteOption === "backtick" || node.parent.type === "TaggedTemplateExpression" && node === node.parent.quasi) { + // Don't throw an error if backticks are expected or a template literal feature is in use. + if (allowTemplateLiterals || quoteOption === "backtick" || isUsingFeatureOfTemplateLiteral(node)) { return; } - // A warning should be produced if the template literal only has one TemplateElement, and has no unescaped newlines. - var shouldWarn = node.quasis.length === 1 && !UNESCAPED_LINEBREAK_PATTERN.test(node.quasis[0].value.raw); + context.report({ + node: node, + message: "Strings must use {{description}}.", + data: { + description: settings.description + }, + fix: function fix(fixer) { + if (isPartOfDirectivePrologue(node)) { - if (shouldWarn) { - context.report({ - node: node, - message: "Strings must use {{description}}.", - data: { - description: settings.description - }, - fix: function fix(fixer) { - if (isPartOfDirectivePrologue(node)) { - - /* - * TemplateLiterals in a directive prologue aren't actually directives, but if they're - * in the directive prologue, then fixing them might turn them into directives and change - * the behavior of the code. - */ - return null; - } - return fixer.replaceText(node, settings.convert(sourceCode.getText(node))); + /* + * TemplateLiterals in a directive prologue aren't actually directives, but if they're + * in the directive prologue, then fixing them might turn them into directives and change + * the behavior of the code. + */ + return null; } - }); - } + return fixer.replaceText(node, settings.convert(sourceCode.getText(node))); + } + }); } }; } }; -},{"../ast-utils":115}],356:[function(require,module,exports){ +},{"../util/ast-utils":405}],357:[function(require,module,exports){ /** * @fileoverview Rule to flag use of parseInt without a radix argument * @author James Allardice @@ -92678,7 +101853,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -92739,6 +101914,8 @@ function isDefaultRadix(radix) { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce the consistent use of the radix argument when using `parseInt()`", category: "Best Practices", @@ -92830,7 +102007,333 @@ module.exports = { } }; -},{"../ast-utils":115}],357:[function(require,module,exports){ +},{"../util/ast-utils":405}],358:[function(require,module,exports){ +/** + * @fileoverview disallow assignments that can lead to race conditions due to usage of `await` or `yield` + * @author Teddy Katz + */ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var astUtils = require("../util/ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "problem", + + docs: { + description: "disallow assignments that can lead to race conditions due to usage of `await` or `yield`", + category: "Possible Errors", + recommended: false, + url: "https://eslint.org/docs/rules/require-atomic-updates" + }, + + fixable: null, + schema: [], + + messages: { + nonAtomicUpdate: "Possible race condition: `{{value}}` might be reassigned based on an outdated value of `{{value}}`." + } + }, + + create: function create(context) { + var sourceCode = context.getSourceCode(); + var identifierToSurroundingFunctionMap = new WeakMap(); + var expressionsByCodePathSegment = new Map(); + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + var resolvedVariableCache = new WeakMap(); + + /** + * Gets the variable scope around this variable reference + * @param {ASTNode} identifier An `Identifier` AST node + * @returns {Scope|null} An escope Scope + */ + function getScope(identifier) { + for (var currentNode = identifier; currentNode; currentNode = currentNode.parent) { + var scope = sourceCode.scopeManager.acquire(currentNode, true); + + if (scope) { + return scope; + } + } + return null; + } + + /** + * Resolves a given identifier to a given scope + * @param {ASTNode} identifier An `Identifier` AST node + * @param {Scope} scope An escope Scope + * @returns {Variable|null} An escope Variable corresponding to the given identifier + */ + function resolveVariableInScope(identifier, scope) { + return scope.variables.find(function (variable) { + return variable.name === identifier.name; + }) || (scope.upper ? resolveVariableInScope(identifier, scope.upper) : null); + } + + /** + * Resolves an identifier to a variable + * @param {ASTNode} identifier An identifier node + * @returns {Variable|null} The escope Variable that uses this identifier + */ + function resolveVariable(identifier) { + if (!resolvedVariableCache.has(identifier)) { + var surroundingScope = getScope(identifier); + + if (surroundingScope) { + resolvedVariableCache.set(identifier, resolveVariableInScope(identifier, surroundingScope)); + } else { + resolvedVariableCache.set(identifier, null); + } + } + + return resolvedVariableCache.get(identifier); + } + + /** + * Checks if an expression is a variable that can only be observed within the given function. + * @param {ASTNode} expression The expression to check + * @param {ASTNode} surroundingFunction The function node + * @returns {boolean} `true` if the expression is a variable which is local to the given function, and is never + * referenced in a closure. + */ + function isLocalVariableWithoutEscape(expression, surroundingFunction) { + if (expression.type !== "Identifier") { + return false; + } + + var variable = resolveVariable(expression); + + if (!variable) { + return false; + } + + return variable.references.every(function (reference) { + return identifierToSurroundingFunctionMap.get(reference.identifier) === surroundingFunction; + }) && variable.defs.every(function (def) { + return identifierToSurroundingFunctionMap.get(def.name) === surroundingFunction; + }); + } + + /** + * Reports an AssignmentExpression node that has a non-atomic update + * @param {ASTNode} assignmentExpression The assignment that is potentially unsafe + * @returns {void} + */ + function reportAssignment(assignmentExpression) { + context.report({ + node: assignmentExpression, + messageId: "nonAtomicUpdate", + data: { + value: sourceCode.getText(assignmentExpression.left) + } + }); + } + + var alreadyReportedAssignments = new WeakSet(); + + var AssignmentTrackerState = function () { + function AssignmentTrackerState() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$openAssignmentsW = _ref.openAssignmentsWithoutReads, + openAssignmentsWithoutReads = _ref$openAssignmentsW === undefined ? new Set() : _ref$openAssignmentsW, + _ref$openAssignmentsW2 = _ref.openAssignmentsWithReads, + openAssignmentsWithReads = _ref$openAssignmentsW2 === undefined ? new Set() : _ref$openAssignmentsW2; + + _classCallCheck(this, AssignmentTrackerState); + + this.openAssignmentsWithoutReads = openAssignmentsWithoutReads; + this.openAssignmentsWithReads = openAssignmentsWithReads; + } + + _createClass(AssignmentTrackerState, [{ + key: "copy", + value: function copy() { + return new AssignmentTrackerState({ + openAssignmentsWithoutReads: new Set(this.openAssignmentsWithoutReads), + openAssignmentsWithReads: new Set(this.openAssignmentsWithReads) + }); + } + }, { + key: "merge", + value: function merge(other) { + var _this = this; + + var initialAssignmentsWithoutReadsCount = this.openAssignmentsWithoutReads.size; + var initialAssignmentsWithReadsCount = this.openAssignmentsWithReads.size; + + other.openAssignmentsWithoutReads.forEach(function (assignment) { + return _this.openAssignmentsWithoutReads.add(assignment); + }); + other.openAssignmentsWithReads.forEach(function (assignment) { + return _this.openAssignmentsWithReads.add(assignment); + }); + + return this.openAssignmentsWithoutReads.size > initialAssignmentsWithoutReadsCount || this.openAssignmentsWithReads.size > initialAssignmentsWithReadsCount; + } + }, { + key: "enterAssignment", + value: function enterAssignment(assignmentExpression) { + (assignmentExpression.operator === "=" ? this.openAssignmentsWithoutReads : this.openAssignmentsWithReads).add(assignmentExpression); + } + }, { + key: "exitAssignment", + value: function exitAssignment(assignmentExpression) { + this.openAssignmentsWithoutReads.delete(assignmentExpression); + this.openAssignmentsWithReads.delete(assignmentExpression); + } + }, { + key: "exitAwaitOrYield", + value: function exitAwaitOrYield(node, surroundingFunction) { + return [].concat(_toConsumableArray(this.openAssignmentsWithReads)).filter(function (assignment) { + return !isLocalVariableWithoutEscape(assignment.left, surroundingFunction); + }).forEach(function (assignment) { + if (!alreadyReportedAssignments.has(assignment)) { + reportAssignment(assignment); + alreadyReportedAssignments.add(assignment); + } + }); + } + }, { + key: "exitIdentifierOrMemberExpression", + value: function exitIdentifierOrMemberExpression(node) { + var _this2 = this; + + [].concat(_toConsumableArray(this.openAssignmentsWithoutReads)).filter(function (assignment) { + return assignment.left !== node && assignment.left.type === node.type && astUtils.equalTokens(assignment.left, node, sourceCode); + }).forEach(function (assignment) { + _this2.openAssignmentsWithoutReads.delete(assignment); + _this2.openAssignmentsWithReads.add(assignment); + }); + } + }]); + + return AssignmentTrackerState; + }(); + + /** + * If the control flow graph of a function enters an assignment expression, then does the + * both of the following steps in order (possibly with other steps in between) before exiting the + * assignment expression, then the assignment might be using an outdated value. + * 1. Enters a read of the variable or property assigned in the expression (not necessary if operator assignment is used) + * 2. Exits an `await` or `yield` expression + * + * This function checks for the outdated values and reports them. + * @param {CodePathSegment} codePathSegment The current code path segment to traverse + * @param {ASTNode} surroundingFunction The function node containing the code path segment + * @returns {void} + */ + + + function findOutdatedReads(codePathSegment, surroundingFunction) { + var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref2$stateBySegmentS = _ref2.stateBySegmentStart, + stateBySegmentStart = _ref2$stateBySegmentS === undefined ? new WeakMap() : _ref2$stateBySegmentS, + _ref2$stateBySegmentE = _ref2.stateBySegmentEnd, + stateBySegmentEnd = _ref2$stateBySegmentE === undefined ? new WeakMap() : _ref2$stateBySegmentE; + + if (!stateBySegmentStart.has(codePathSegment)) { + stateBySegmentStart.set(codePathSegment, new AssignmentTrackerState()); + } + + var currentState = stateBySegmentStart.get(codePathSegment).copy(); + + expressionsByCodePathSegment.get(codePathSegment).forEach(function (_ref3) { + var entering = _ref3.entering, + node = _ref3.node; + + if (node.type === "AssignmentExpression") { + if (entering) { + currentState.enterAssignment(node); + } else { + currentState.exitAssignment(node); + } + } else if (!entering && (node.type === "AwaitExpression" || node.type === "YieldExpression")) { + currentState.exitAwaitOrYield(node, surroundingFunction); + } else if (!entering && (node.type === "Identifier" || node.type === "MemberExpression")) { + currentState.exitIdentifierOrMemberExpression(node); + } + }); + + stateBySegmentEnd.set(codePathSegment, currentState); + + codePathSegment.nextSegments.forEach(function (nextSegment) { + if (stateBySegmentStart.has(nextSegment)) { + if (!stateBySegmentStart.get(nextSegment).merge(currentState)) { + + /* + * This segment has already been processed with the given set of inputs; + * no need to do it again. After no new state is available to process + * for any control flow segment in the graph, the analysis reaches a fixpoint and + * traversal stops. + */ + return; + } + } else { + stateBySegmentStart.set(nextSegment, currentState.copy()); + } + findOutdatedReads(nextSegment, surroundingFunction, { stateBySegmentStart: stateBySegmentStart, stateBySegmentEnd: stateBySegmentEnd }); + }); + } + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + var currentCodePathSegmentStack = []; + var currentCodePathSegment = null; + var functionStack = []; + + return { + onCodePathStart: function onCodePathStart() { + currentCodePathSegmentStack.push(currentCodePathSegment); + }, + onCodePathEnd: function onCodePathEnd(codePath, node) { + currentCodePathSegment = currentCodePathSegmentStack.pop(); + + if (astUtils.isFunction(node) && (node.async || node.generator)) { + findOutdatedReads(codePath.initialSegment, node); + } + }, + onCodePathSegmentStart: function onCodePathSegmentStart(segment) { + currentCodePathSegment = segment; + expressionsByCodePathSegment.set(segment, []); + }, + "AssignmentExpression, Identifier, MemberExpression, AwaitExpression, YieldExpression": function AssignmentExpressionIdentifierMemberExpressionAwaitExpressionYieldExpression(node) { + expressionsByCodePathSegment.get(currentCodePathSegment).push({ entering: true, node: node }); + }, + "AssignmentExpression, Identifier, MemberExpression, AwaitExpression, YieldExpression:exit": function AssignmentExpressionIdentifierMemberExpressionAwaitExpressionYieldExpressionExit(node) { + expressionsByCodePathSegment.get(currentCodePathSegment).push({ entering: false, node: node }); + }, + ":function": function _function(node) { + functionStack.push(node); + }, + ":function:exit": function functionExit() { + functionStack.pop(); + }, + Identifier: function Identifier(node) { + if (functionStack.length) { + identifierToSurroundingFunctionMap.set(node, functionStack[functionStack.length - 1]); + } + } + }; + } +}; + +},{"../util/ast-utils":405}],359:[function(require,module,exports){ /** * @fileoverview Rule to disallow async functions which have no `await` expression. * @author Toru Nagashima @@ -92842,7 +102345,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -92864,12 +102367,15 @@ function capitalizeFirstLetter(text) { module.exports = { meta: { + type: "suggestion", + docs: { description: "disallow async functions which have no `await` expression", category: "Best Practices", recommended: false, url: "https://eslint.org/docs/rules/require-await" }, + schema: [] }, @@ -92931,7 +102437,7 @@ module.exports = { } }; -},{"../ast-utils":115}],358:[function(require,module,exports){ +},{"../util/ast-utils":405}],360:[function(require,module,exports){ /** * @fileoverview Rule to check for jsdoc presence. * @author Gyandeep Singh @@ -92940,6 +102446,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require JSDoc comments", category: "Stylistic Issues", @@ -92973,7 +102481,10 @@ module.exports = { } }, additionalProperties: false - }] + }], + + deprecated: true, + replacedBy: [] }, create: function create(context) { @@ -93034,7 +102545,101 @@ module.exports = { } }; -},{}],359:[function(require,module,exports){ +},{}],361:[function(require,module,exports){ +/** + * @fileoverview Rule to enforce the use of `u` flag on RegExp. + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var _require = require("eslint-utils"), + CALL = _require.CALL, + CONSTRUCT = _require.CONSTRUCT, + ReferenceTracker = _require.ReferenceTracker, + getStringIfConstant = _require.getStringIfConstant; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "enforce the use of `u` flag on RegExp", + category: "Best Practices", + recommended: false, + url: "https://eslint.org/docs/rules/require-unicode-regexp" + }, + + messages: { + requireUFlag: "Use the 'u' flag." + }, + + schema: [] + }, + + create: function create(context) { + return { + "Literal[regex]": function LiteralRegex(node) { + var flags = node.regex.flags || ""; + + if (!flags.includes("u")) { + context.report({ node: node, messageId: "requireUFlag" }); + } + }, + Program: function Program() { + var _RegExp; + + var scope = context.getScope(); + var tracker = new ReferenceTracker(scope); + var trackMap = { + RegExp: (_RegExp = {}, _defineProperty(_RegExp, CALL, true), _defineProperty(_RegExp, CONSTRUCT, true), _RegExp) + }; + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = tracker.iterateGlobalReferences(trackMap)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var node = _step.value.node; + + var flagsNode = node.arguments[1]; + var flags = getStringIfConstant(flagsNode, scope); + + if (!flagsNode || typeof flags === "string" && !flags.includes("u")) { + context.report({ node: node, messageId: "requireUFlag" }); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + }; + } +}; + +},{"eslint-utils":68}],362:[function(require,module,exports){ /** * @fileoverview Rule to flag the generator functions that does not have yield. * @author Toru Nagashima @@ -93048,6 +102653,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require generator functions to contain `yield`", category: "ECMAScript 6", @@ -93108,7 +102715,7 @@ module.exports = { } }; -},{}],360:[function(require,module,exports){ +},{}],363:[function(require,module,exports){ /** * @fileoverview Enforce spacing between rest and spread operators and their expressions. * @author Kai Cataldo @@ -93122,13 +102729,17 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "enforce spacing between rest and spread operators and their expressions", category: "ECMAScript 6", recommended: false, url: "https://eslint.org/docs/rules/rest-spread-spacing" }, + fixable: "whitespace", + schema: [{ enum: ["always", "never"] }] @@ -93222,7 +102833,7 @@ module.exports = { } }; -},{}],361:[function(require,module,exports){ +},{}],364:[function(require,module,exports){ /** * @fileoverview Validates spacing before and after semicolon * @author Mathias Schreck @@ -93232,7 +102843,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -93240,6 +102851,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before and after semicolons", category: "Stylistic Issues", @@ -93271,10 +102884,10 @@ module.exports = { requireSpaceAfter = true; if ((typeof config === "undefined" ? "undefined" : _typeof(config)) === "object") { - if (config.hasOwnProperty("before")) { + if (Object.prototype.hasOwnProperty.call(config, "before")) { requireSpaceBefore = config.before; } - if (config.hasOwnProperty("after")) { + if (Object.prototype.hasOwnProperty.call(config, "after")) { requireSpaceAfter = config.after; } } @@ -93436,7 +103049,7 @@ module.exports = { } }; -},{"../ast-utils":115}],362:[function(require,module,exports){ +},{"../util/ast-utils":405}],365:[function(require,module,exports){ /** * @fileoverview Rule to enforce location of semicolons. * @author Toru Nagashima @@ -93450,7 +103063,7 @@ module.exports = { function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -93500,12 +103113,15 @@ function isLastChild(node) { module.exports = { meta: { + type: "layout", + docs: { description: "enforce location of semicolons", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/semi-style" }, + schema: [{ enum: ["last", "first"] }], fixable: "whitespace" }, @@ -93574,7 +103190,7 @@ module.exports = { } }; -},{"../ast-utils":115}],363:[function(require,module,exports){ +},{"../util/ast-utils":405}],366:[function(require,module,exports){ /** * @fileoverview Rule to flag missing semicolons. * @author Nicholas C. Zakas @@ -93586,7 +103202,7 @@ module.exports = { //------------------------------------------------------------------------------ var FixTracker = require("../util/fix-tracker"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -93594,6 +103210,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow semicolons instead of ASI", category: "Stylistic Issues", @@ -93865,7 +103483,7 @@ module.exports = { } }; -},{"../ast-utils":115,"../util/fix-tracker":403}],364:[function(require,module,exports){ +},{"../util/ast-utils":405,"../util/fix-tracker":407}],367:[function(require,module,exports){ /** * @fileoverview Rule to require sorting of import declarations * @author Christian Schuller @@ -93879,6 +103497,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce sorted import declarations within modules", category: "ECMAScript 6", @@ -94061,7 +103681,7 @@ module.exports = { } }; -},{}],365:[function(require,module,exports){ +},{}],368:[function(require,module,exports){ /** * @fileoverview Rule to require object keys to be sorted * @author Toru Nagashima @@ -94073,7 +103693,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"), +var astUtils = require("../util/ast-utils"), naturalCompare = require("natural-compare"); //------------------------------------------------------------------------------ @@ -94137,12 +103757,15 @@ var isValidOrders = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require object keys to be sorted", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/sort-keys" }, + schema: [{ enum: ["asc", "desc"] }, { @@ -94182,7 +103805,9 @@ module.exports = { stack = stack.upper; }, Property: function Property(node) { - if (node.parent.type === "ObjectPattern") { + if (node.parent.type === "ObjectPattern" || node.parent.properties.some(function (n) { + return n.type === "SpreadElement"; + })) { return; } @@ -94214,7 +103839,7 @@ module.exports = { } }; -},{"../ast-utils":115,"natural-compare":92}],366:[function(require,module,exports){ +},{"../util/ast-utils":405,"natural-compare":95}],369:[function(require,module,exports){ /** * @fileoverview Rule to require sorting of variables within a single Variable Declaration block * @author Ilya Volodin @@ -94228,6 +103853,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require variables within the same declaration block to be sorted", category: "Stylistic Issues", @@ -94312,7 +103939,7 @@ module.exports = { } }; -},{}],367:[function(require,module,exports){ +},{}],370:[function(require,module,exports){ /** * @fileoverview A rule to ensure whitespace before blocks. * @author Mathias Schreck @@ -94322,7 +103949,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -94330,6 +103957,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before blocks", category: "Stylistic Issues", @@ -94346,13 +103975,13 @@ module.exports = { type: "object", properties: { keywords: { - enum: ["always", "never"] + enum: ["always", "never", "off"] }, functions: { - enum: ["always", "never"] + enum: ["always", "never", "off"] }, classes: { - enum: ["always", "never"] + enum: ["always", "never", "off"] } }, additionalProperties: false @@ -94363,18 +103992,27 @@ module.exports = { create: function create(context) { var config = context.options[0], sourceCode = context.getSourceCode(); - var checkFunctions = true, - checkKeywords = true, - checkClasses = true; + var alwaysFunctions = true, + alwaysKeywords = true, + alwaysClasses = true, + neverFunctions = false, + neverKeywords = false, + neverClasses = false; if ((typeof config === "undefined" ? "undefined" : _typeof(config)) === "object") { - checkFunctions = config.functions !== "never"; - checkKeywords = config.keywords !== "never"; - checkClasses = config.classes !== "never"; + alwaysFunctions = config.functions === "always"; + alwaysKeywords = config.keywords === "always"; + alwaysClasses = config.classes === "always"; + neverFunctions = config.functions === "never"; + neverKeywords = config.keywords === "never"; + neverClasses = config.classes === "never"; } else if (config === "never") { - checkFunctions = false; - checkKeywords = false; - checkClasses = false; + alwaysFunctions = false; + alwaysKeywords = false; + alwaysClasses = false; + neverFunctions = true; + neverKeywords = true; + neverClasses = true; } /** @@ -94400,35 +104038,35 @@ module.exports = { var hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); var parent = context.getAncestors().pop(); var requireSpace = void 0; + var requireNoSpace = void 0; if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") { - requireSpace = checkFunctions; + requireSpace = alwaysFunctions; + requireNoSpace = neverFunctions; } else if (node.type === "ClassBody") { - requireSpace = checkClasses; + requireSpace = alwaysClasses; + requireNoSpace = neverClasses; } else { - requireSpace = checkKeywords; + requireSpace = alwaysKeywords; + requireNoSpace = neverKeywords; } - if (requireSpace) { - if (!hasSpace) { - context.report({ - node: node, - message: "Missing space before opening brace.", - fix: function fix(fixer) { - return fixer.insertTextBefore(node, " "); - } - }); - } - } else { - if (hasSpace) { - context.report({ - node: node, - message: "Unexpected space before opening brace.", - fix: function fix(fixer) { - return fixer.removeRange([precedingToken.range[1], node.range[0]]); - } - }); - } + if (requireSpace && !hasSpace) { + context.report({ + node: node, + message: "Missing space before opening brace.", + fix: function fix(fixer) { + return fixer.insertTextBefore(node, " "); + } + }); + } else if (requireNoSpace && hasSpace) { + context.report({ + node: node, + message: "Unexpected space before opening brace.", + fix: function fix(fixer) { + return fixer.removeRange([precedingToken.range[1], node.range[0]]); + } + }); } } } @@ -94459,7 +104097,7 @@ module.exports = { } }; -},{"../ast-utils":115}],368:[function(require,module,exports){ +},{"../util/ast-utils":405}],371:[function(require,module,exports){ /** * @fileoverview Rule to validate spacing before function paren. * @author Mathias Schreck @@ -94472,7 +104110,7 @@ module.exports = { var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -94480,6 +104118,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before `function` definition opening parenthesis", category: "Stylistic Issues", @@ -94598,14 +104238,14 @@ module.exports = { } }; -},{"../ast-utils":115}],369:[function(require,module,exports){ +},{"../util/ast-utils":405}],372:[function(require,module,exports){ /** * @fileoverview Disallows or enforces spaces inside of parentheses. * @author Jonathan Rajavuori */ "use strict"; -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -94613,6 +104253,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing inside parentheses", category: "Stylistic Issues", @@ -94657,7 +104299,6 @@ module.exports = { /** * Produces an object with the opener and closer exception values - * @param {Object} opts The exception options * @returns {Object} `openers` and `closers` exception values * @private */ @@ -94867,7 +104508,7 @@ module.exports = { } }; -},{"../ast-utils":115}],370:[function(require,module,exports){ +},{"../util/ast-utils":405}],373:[function(require,module,exports){ /** * @fileoverview Require spaces around infix operators * @author Michael Ficarra @@ -94880,6 +104521,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require spacing around infix operators", category: "Stylistic Issues", @@ -94902,28 +104545,27 @@ module.exports = { create: function create(context) { var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; - - var OPERATORS = ["*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in", "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", "?", ":", ",", "**"]; - var sourceCode = context.getSourceCode(); /** * Returns the first token which violates the rule * @param {ASTNode} left - The left node of the main node * @param {ASTNode} right - The right node of the main node + * @param {string} op - The operator of the main node * @returns {Object} The violator token or null * @private */ - function getFirstNonSpacedToken(left, right) { - var tokens = sourceCode.getTokensBetween(left, right, 1); + function getFirstNonSpacedToken(left, right, op) { + var operator = sourceCode.getFirstTokenBetween(left, right, function (token) { + return token.value === op; + }); + var prev = sourceCode.getTokenBefore(operator); + var next = sourceCode.getTokenAfter(operator); - for (var i = 1, l = tokens.length - 1; i < l; ++i) { - var op = tokens[i]; - - if ((op.type === "Punctuator" || op.type === "Keyword") && OPERATORS.indexOf(op.value) >= 0 && (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])) { - return op; - } + if (!sourceCode.isSpaceBetweenTokens(prev, operator) || !sourceCode.isSpaceBetweenTokens(operator, next)) { + return operator; } + return null; } @@ -94938,7 +104580,10 @@ module.exports = { context.report({ node: mainNode, loc: culpritToken.loc.start, - message: "Infix operators must be spaced.", + message: "Operator '{{operator}}' must be spaced.", + data: { + operator: culpritToken.value + }, fix: function fix(fixer) { var previousToken = sourceCode.getTokenBefore(culpritToken); var afterToken = sourceCode.getTokenAfter(culpritToken); @@ -94969,7 +104614,10 @@ module.exports = { var leftNode = node.left.typeAnnotation ? node.left.typeAnnotation : node.left; var rightNode = node.right; - var nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode); + // search for = in AssignmentPattern nodes + var operator = node.operator || "="; + + var nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode, operator); if (nonSpacedNode) { if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) { @@ -94985,8 +104633,8 @@ module.exports = { * @private */ function checkConditional(node) { - var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); - var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); + var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent, "?"); + var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate, ":"); if (nonSpacedConsequesntNode) { report(node, nonSpacedConsequesntNode); @@ -95006,7 +104654,7 @@ module.exports = { var rightNode = node.init; if (rightNode) { - var nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode); + var nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode, "="); if (nonSpacedNode) { report(node, nonSpacedNode); @@ -95025,7 +104673,7 @@ module.exports = { } }; -},{}],371:[function(require,module,exports){ +},{}],374:[function(require,module,exports){ /** * @fileoverview This rule shoud require or disallow spaces before or after unary operations. * @author Marcin Kumorek @@ -95036,7 +104684,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -95044,6 +104692,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce consistent spacing before or after unary operators", category: "Stylistic Issues", @@ -95097,7 +104747,7 @@ module.exports = { * @returns {boolean} Whether or not an override has been provided for the operator */ function overrideExistsForOperator(operator) { - return options.overrides && options.overrides.hasOwnProperty(operator); + return options.overrides && Object.prototype.hasOwnProperty.call(options.overrides, operator); } /** @@ -95166,8 +104816,6 @@ module.exports = { * @returns {void} */ function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) { - word = word || firstToken.value; - if (overrideExistsForOperator(word)) { if (overrideEnforcesSpaces(word)) { verifyWordHasSpaces(node, firstToken, secondToken, word); @@ -95299,7 +104947,7 @@ module.exports = { var secondToken = tokens[1]; if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") { - checkUnaryWordOperatorForSpaces(node, firstToken, secondToken); + checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, firstToken.value); return; } @@ -95332,7 +104980,7 @@ module.exports = { } }; -},{"../ast-utils":115}],372:[function(require,module,exports){ +},{"../util/ast-utils":405}],375:[function(require,module,exports){ /** * @fileoverview Source code for spaced-comments rule * @author Gyandeep Singh @@ -95340,7 +104988,7 @@ module.exports = { "use strict"; var lodash = require("lodash"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -95352,10 +105000,7 @@ var astUtils = require("../ast-utils"); * @returns {string} An escaped string. */ function escape(s) { - var isOneChar = s.length === 1; - - s = lodash.escapeRegExp(s); - return isOneChar ? s : "(?:" + s + ")"; + return "(?:" + lodash.escapeRegExp(s) + ")"; } /** @@ -95375,11 +105020,10 @@ function escapeAndRepeat(s) { * @returns {string[]} A marker list. */ function parseMarkersOption(markers) { - markers = markers ? markers.slice(0) : []; // `*` is a marker for JSDoc comments. if (markers.indexOf("*") === -1) { - markers.push("*"); + return markers.concat("*"); } return markers; @@ -95490,6 +105134,8 @@ function createNeverStylePattern(markers) { module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce consistent spacing after the `//` or `/*` in a comment", category: "Stylistic Issues", @@ -95576,7 +105222,7 @@ module.exports = { var balanced = config.block && config.block.balanced; var styleRules = ["block", "line"].reduce(function (rule, type) { - var markers = parseMarkersOption(config[type] && config[type].markers || config.markers); + var markers = parseMarkersOption(config[type] && config[type].markers || config.markers || []); var exceptions = config[type] && config[type].exceptions || config.exceptions || []; var endNeverPattern = "[ \t]+$"; @@ -95709,7 +105355,7 @@ module.exports = { } }; -},{"../ast-utils":115,"lodash":89}],373:[function(require,module,exports){ +},{"../util/ast-utils":405,"lodash":92}],376:[function(require,module,exports){ /** * @fileoverview Rule to control usage of strict mode directives. * @author Brandon Mills @@ -95721,7 +105367,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -95788,6 +105434,8 @@ function isSimpleParameterList(params) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow strict mode directives", category: "Strict Mode", @@ -95986,7 +105634,7 @@ module.exports = { } }; -},{"../ast-utils":115}],374:[function(require,module,exports){ +},{"../util/ast-utils":405}],377:[function(require,module,exports){ /** * @fileoverview Rule to enforce spacing around colons of switch statements. * @author Toru Nagashima @@ -95998,7 +105646,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -96006,12 +105654,15 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "enforce spacing around colons of switch statements", category: "Stylistic Issues", recommended: false, url: "https://eslint.org/docs/rules/switch-colon-spacing" }, + schema: [{ type: "object", properties: { @@ -96020,6 +105671,7 @@ module.exports = { }, additionalProperties: false }], + fixable: "whitespace" }, @@ -96116,7 +105768,7 @@ module.exports = { } }; -},{"../ast-utils":115}],375:[function(require,module,exports){ +},{"../util/ast-utils":405}],378:[function(require,module,exports){ /** * @fileoverview Rule to enforce description with the `Symbol` object * @author Jarek Rencz @@ -96128,7 +105780,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -96137,6 +105789,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "suggestion", + docs: { description: "require symbol descriptions", category: "ECMAScript 6", @@ -96184,7 +105838,7 @@ module.exports = { } }; -},{"../ast-utils":115}],376:[function(require,module,exports){ +},{"../util/ast-utils":405}],379:[function(require,module,exports){ /** * @fileoverview Rule to enforce spacing around embedded expressions of template strings * @author Toru Nagashima @@ -96196,7 +105850,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -96211,6 +105865,8 @@ var CLOSE_PAREN = /^\}/; module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow spacing around embedded expressions of template strings", category: "ECMAScript 6", @@ -96292,7 +105948,7 @@ module.exports = { } }; -},{"../ast-utils":115}],377:[function(require,module,exports){ +},{"../util/ast-utils":405}],380:[function(require,module,exports){ /** * @fileoverview Rule to check spacing between template tags and their literals * @author Jonathan Wilsson @@ -96306,6 +105962,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow spacing between template tags and their literals", category: "Stylistic Issues", @@ -96371,7 +106029,7 @@ module.exports = { } }; -},{}],378:[function(require,module,exports){ +},{}],381:[function(require,module,exports){ /** * @fileoverview Require or disallow Unicode BOM * @author Andrew Johnston @@ -96384,6 +106042,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow Unicode byte order mark (BOM)", category: "Stylistic Issues", @@ -96437,7 +106097,7 @@ module.exports = { } }; -},{}],379:[function(require,module,exports){ +},{}],382:[function(require,module,exports){ /** * @fileoverview Rule to flag comparisons to the value NaN * @author James Allardice @@ -96451,6 +106111,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "require calls to `isNaN()` when checking for `NaN`", category: "Possible Errors", @@ -96473,7 +106135,7 @@ module.exports = { } }; -},{}],380:[function(require,module,exports){ +},{}],383:[function(require,module,exports){ /** * @fileoverview Validates JSDoc comments are syntactically correct * @author Nicholas C. Zakas @@ -96492,6 +106154,8 @@ var doctrine = require("doctrine"); module.exports = { meta: { + type: "suggestion", + docs: { description: "enforce valid JSDoc comments", category: "Possible Errors", @@ -96528,12 +106192,18 @@ module.exports = { }, requireReturnType: { type: "boolean" + }, + requireParamType: { + type: "boolean" } }, additionalProperties: false }], - fixable: "code" + fixable: "code", + + deprecated: true, + replacedBy: [] }, create: function create(context) { @@ -96548,6 +106218,7 @@ module.exports = { requireParamDescription = options.requireParamDescription !== false, requireReturnDescription = options.requireReturnDescription !== false, requireReturnType = options.requireReturnType !== false, + requireParamType = options.requireParamType !== false, preferType = options.preferType || {}, checkPreferType = Object.keys(preferType).length !== 0; @@ -96576,7 +106247,7 @@ module.exports = { */ function startFunction(node) { fns.push({ - returnPresent: node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement" || isTypeClass(node) + returnPresent: node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement" || isTypeClass(node) || node.async }); } @@ -96794,7 +106465,7 @@ module.exports = { } // check tag preferences - if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) { + if (Object.prototype.hasOwnProperty.call(prefer, tag.title) && tag.title !== prefer[tag.title]) { var entireTagRange = getAbsoluteRange(jsdocNode, tag); context.report({ @@ -96821,7 +106492,7 @@ module.exports = { }); paramTags.forEach(function (param) { - if (!param.type) { + if (requireParamType && !param.type) { context.report({ node: jsdocNode, message: "Missing JSDoc parameter type for '{{name}}'.", @@ -96872,7 +106543,7 @@ module.exports = { // check for functions missing @returns if (!isOverride && !hasReturns && !hasConstructor && !isInterface && node.parent.kind !== "get" && node.parent.kind !== "constructor" && node.parent.kind !== "set" && !isTypeClass(node)) { - if (requireReturn || functionData.returnPresent) { + if (requireReturn || functionData.returnPresent && !node.async) { context.report({ node: jsdocNode, message: "Missing JSDoc @{{returns}} for function.", @@ -96888,14 +106559,12 @@ module.exports = { if (node.params) { node.params.forEach(function (param, paramsIndex) { - if (param.type === "AssignmentPattern") { - param = param.left; - } - - var name = param.name; + var bindingParam = param.type === "AssignmentPattern" ? param.left : param; // TODO(nzakas): Figure out logical things to do with destructured, default, rest params - if (param.type === "Identifier") { + if (bindingParam.type === "Identifier") { + var name = bindingParam.name; + if (jsdocParamNames[paramsIndex] && name !== jsdocParamNames[paramsIndex]) { context.report({ node: jsdocNode, @@ -96949,7 +106618,7 @@ module.exports = { } }; -},{"doctrine":54}],381:[function(require,module,exports){ +},{"doctrine":55}],384:[function(require,module,exports){ /** * @fileoverview Ensures that the results of typeof are compared against a valid string * @author Ian Christian Myers @@ -96962,6 +106631,8 @@ module.exports = { module.exports = { meta: { + type: "problem", + docs: { description: "enforce comparing `typeof` expressions against valid strings", category: "Possible Errors", @@ -97024,7 +106695,7 @@ module.exports = { } }; -},{}],382:[function(require,module,exports){ +},{}],385:[function(require,module,exports){ /** * @fileoverview Rule to enforce var declarations are only at the top of a function. * @author Danny Fritz @@ -97038,6 +106709,8 @@ module.exports = { module.exports = { meta: { + type: "suggestion", + docs: { description: "require `var` declarations be placed at the top of their containing scope", category: "Best Practices", @@ -97141,32 +106814,20 @@ module.exports = { //-------------------------------------------------------------------------- return { - VariableDeclaration: function VariableDeclaration(node) { - var ancestors = context.getAncestors(); - var parent = ancestors.pop(); - var grandParent = ancestors.pop(); - - if (node.kind === "var") { - // check variable is `var` type and not `let` or `const` - if (parent.type === "ExportNamedDeclaration") { - node = parent; - parent = grandParent; - grandParent = ancestors.pop(); - } - - if (parent.type === "Program") { - // That means its a global variable - globalVarCheck(node, parent); - } else { - blockScopeVarCheck(node, parent, grandParent); - } + "VariableDeclaration[kind='var']": function VariableDeclarationKindVar(node) { + if (node.parent.type === "ExportNamedDeclaration") { + globalVarCheck(node.parent, node.parent.parent); + } else if (node.parent.type === "Program") { + globalVarCheck(node, node.parent); + } else { + blockScopeVarCheck(node, node.parent, node.parent.parent); } } }; } }; -},{}],383:[function(require,module,exports){ +},{}],386:[function(require,module,exports){ /** * @fileoverview Rule to flag when IIFE is not wrapped in parens * @author Ilya Volodin @@ -97178,7 +106839,7 @@ module.exports = { // Requirements //------------------------------------------------------------------------------ -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -97186,6 +106847,8 @@ var astUtils = require("../ast-utils"); module.exports = { meta: { + type: "layout", + docs: { description: "require parentheses around immediate `function` invocations", category: "Best Practices", @@ -97305,7 +106968,7 @@ module.exports = { } }; -},{"../ast-utils":115}],384:[function(require,module,exports){ +},{"../util/ast-utils":405}],387:[function(require,module,exports){ /** * @fileoverview Rule to flag when regex literals are not wrapped in parens * @author Matt DuVall @@ -97319,6 +106982,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require parenthesis around regex literals", category: "Stylistic Issues", @@ -97327,8 +106992,11 @@ module.exports = { }, schema: [], + fixable: "code", - fixable: "code" + messages: { + requireParens: "Wrap the regexp literal in parens to disambiguate the slash." + } }, create: function create(context) { @@ -97340,14 +107008,15 @@ module.exports = { nodeType = token.type; if (nodeType === "RegularExpression") { - var source = sourceCode.getTokenBefore(node); + var beforeToken = sourceCode.getTokenBefore(node); + var afterToken = sourceCode.getTokenAfter(node); var ancestors = context.getAncestors(); var grandparent = ancestors[ancestors.length - 1]; - if (grandparent.type === "MemberExpression" && grandparent.object === node && (!source || source.value !== "(")) { + if (grandparent.type === "MemberExpression" && grandparent.object === node && !(beforeToken && beforeToken.value === "(" && afterToken && afterToken.value === ")")) { context.report({ node: node, - message: "Wrap the regexp literal in parens to disambiguate the slash.", + messageId: "requireParens", fix: function fix(fixer) { return fixer.replaceText(node, "(" + sourceCode.getText(node) + ")"); } @@ -97359,7 +107028,7 @@ module.exports = { } }; -},{}],385:[function(require,module,exports){ +},{}],388:[function(require,module,exports){ /** * @fileoverview Rule to check the spacing around the * in yield* expressions. * @author Bryan Smith @@ -97373,6 +107042,8 @@ module.exports = { module.exports = { meta: { + type: "layout", + docs: { description: "require or disallow spacing around the `*` in `yield*` expressions", category: "ECMAScript 6", @@ -97473,7 +107144,7 @@ module.exports = { } }; -},{}],386:[function(require,module,exports){ +},{}],389:[function(require,module,exports){ /** * @fileoverview Rule to require or disallow yoda comparisons * @author Nicholas C. Zakas @@ -97484,7 +107155,7 @@ module.exports = { // Requirements //-------------------------------------------------------------------------- -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //-------------------------------------------------------------------------- // Helpers @@ -97620,6 +107291,8 @@ function same(a, b) { module.exports = { meta: { + type: "suggestion", + docs: { description: "require or disallow \"Yoda\" conditions", category: "Best Practices", @@ -97759,151 +107432,7 @@ module.exports = { } }; -},{"../ast-utils":115}],387:[function(require,module,exports){ -(function (process){ -/** - * @fileoverview Tracks performance of individual rules. - * @author Brandon Mills - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -/* istanbul ignore next */ -/** - * Align the string to left - * @param {string} str string to evaluate - * @param {int} len length of the string - * @param {string} ch delimiter character - * @returns {string} modified string - * @private - */ - -function alignLeft(str, len, ch) { - return str + new Array(len - str.length + 1).join(ch || " "); -} - -/* istanbul ignore next */ -/** - * Align the string to right - * @param {string} str string to evaluate - * @param {int} len length of the string - * @param {string} ch delimiter character - * @returns {string} modified string - * @private - */ -function alignRight(str, len, ch) { - return new Array(len - str.length + 1).join(ch || " ") + str; -} - -//------------------------------------------------------------------------------ -// Module definition -//------------------------------------------------------------------------------ - -var enabled = !!process.env.TIMING; - -var HEADERS = ["Rule", "Time (ms)", "Relative"]; -var ALIGN = [alignLeft, alignRight, alignRight]; - -/* istanbul ignore next */ -/** - * display the data - * @param {Object} data Data object to be displayed - * @returns {string} modified string - * @private - */ -function display(data) { - var total = 0; - var rows = Object.keys(data).map(function (key) { - var time = data[key]; - - total += time; - return [key, time]; - }).sort(function (a, b) { - return b[1] - a[1]; - }).slice(0, 10); - - rows.forEach(function (row) { - row.push((row[1] * 100 / total).toFixed(1) + "%"); - row[1] = row[1].toFixed(3); - }); - - rows.unshift(HEADERS); - - var widths = []; - - rows.forEach(function (row) { - var len = row.length; - - for (var i = 0; i < len; i++) { - var n = row[i].length; - - if (!widths[i] || n > widths[i]) { - widths[i] = n; - } - } - }); - - var table = rows.map(function (row) { - return row.map(function (cell, index) { - return ALIGN[index](cell, widths[index]); - }).join(" | "); - }); - - table.splice(1, 0, widths.map(function (w, index) { - if (index !== 0 && index !== widths.length - 1) { - w++; - } - - return ALIGN[index](":", w + 1, "-"); - }).join("|")); - - console.log(table.join("\n")); // eslint-disable-line no-console -} - -/* istanbul ignore next */ -module.exports = function () { - - var data = Object.create(null); - - /** - * Time the run - * @param {*} key key from the data object - * @param {Function} fn function to be called - * @returns {Function} function to be executed - * @private - */ - function time(key, fn) { - if (typeof data[key] === "undefined") { - data[key] = 0; - } - - return function () { - var t = process.hrtime(); - - fn.apply(null, Array.prototype.slice.call(arguments)); - t = process.hrtime(t); - data[key] += t[0] * 1e3 + t[1] / 1e6; - }; - } - - if (enabled) { - process.on("exit", function () { - display(data); - }); - } - - return { - time: time, - enabled: enabled - }; -}(); - -}).call(this,require('_process')) -},{"_process":101}],388:[function(require,module,exports){ +},{"../util/ast-utils":405}],390:[function(require,module,exports){ /** * @fileoverview Define the cursor which iterates tokens and comments in reverse. * @author Toru Nagashima @@ -97982,7 +107511,7 @@ module.exports = function (_Cursor) { return BackwardTokenCommentCursor; }(Cursor); -},{"./cursor":390,"./utils":400}],389:[function(require,module,exports){ +},{"./cursor":392,"./utils":402}],391:[function(require,module,exports){ /** * @fileoverview Define the cursor which iterates tokens only in reverse. * @author Toru Nagashima @@ -98065,7 +107594,7 @@ module.exports = function (_Cursor) { return BackwardTokenCursor; }(Cursor); -},{"./cursor":390,"./utils":400}],390:[function(require,module,exports){ +},{"./cursor":392,"./utils":402}],392:[function(require,module,exports){ /** * @fileoverview Define the abstract class about cursors which iterate tokens. * @author Toru Nagashima @@ -98164,7 +107693,7 @@ module.exports = function () { return Cursor; }(); -},{}],391:[function(require,module,exports){ +},{}],393:[function(require,module,exports){ /** * @fileoverview Define 2 token factories; forward and backward. * @author Toru Nagashima @@ -98275,7 +107804,7 @@ var CursorFactory = function () { exports.forward = new CursorFactory(ForwardTokenCursor, ForwardTokenCommentCursor); exports.backward = new CursorFactory(BackwardTokenCursor, BackwardTokenCommentCursor); -},{"./backward-token-comment-cursor":388,"./backward-token-cursor":389,"./filter-cursor":393,"./forward-token-comment-cursor":394,"./forward-token-cursor":395,"./limit-cursor":397,"./skip-cursor":399}],392:[function(require,module,exports){ +},{"./backward-token-comment-cursor":390,"./backward-token-cursor":391,"./filter-cursor":395,"./forward-token-comment-cursor":396,"./forward-token-cursor":397,"./limit-cursor":399,"./skip-cursor":401}],394:[function(require,module,exports){ /** * @fileoverview Define the abstract class about cursors which manipulate another cursor. * @author Toru Nagashima @@ -98336,7 +107865,7 @@ module.exports = function (_Cursor) { return DecorativeCursor; }(Cursor); -},{"./cursor":390}],393:[function(require,module,exports){ +},{"./cursor":392}],395:[function(require,module,exports){ /** * @fileoverview Define the cursor which ignores specified tokens. * @author Toru Nagashima @@ -98403,7 +107932,7 @@ module.exports = function (_DecorativeCursor) { return FilterCursor; }(DecorativeCursor); -},{"./decorative-cursor":392}],394:[function(require,module,exports){ +},{"./decorative-cursor":394}],396:[function(require,module,exports){ /** * @fileoverview Define the cursor which iterates tokens and comments. * @author Toru Nagashima @@ -98482,7 +108011,7 @@ module.exports = function (_Cursor) { return ForwardTokenCommentCursor; }(Cursor); -},{"./cursor":390,"./utils":400}],395:[function(require,module,exports){ +},{"./cursor":392,"./utils":402}],397:[function(require,module,exports){ /** * @fileoverview Define the cursor which iterates tokens only. * @author Toru Nagashima @@ -98573,7 +108102,7 @@ module.exports = function (_Cursor) { return ForwardTokenCursor; }(Cursor); -},{"./cursor":390,"./utils":400}],396:[function(require,module,exports){ +},{"./cursor":392,"./utils":402}],398:[function(require,module,exports){ /** * @fileoverview Object to handle access and retrieval of tokens. * @author Brandon Mills @@ -98593,7 +108122,7 @@ var cursors = require("./cursors"); var ForwardTokenCursor = require("./forward-token-cursor"); var PaddedTokenCursor = require("./padded-token-cursor"); var utils = require("./utils"); -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -99143,7 +108672,7 @@ module.exports = function () { return TokenStore; }(); -},{"../ast-utils":115,"./cursors":391,"./forward-token-cursor":395,"./padded-token-cursor":398,"./utils":400,"assert":47}],397:[function(require,module,exports){ +},{"../util/ast-utils":405,"./cursors":393,"./forward-token-cursor":397,"./padded-token-cursor":400,"./utils":402,"assert":46}],399:[function(require,module,exports){ /** * @fileoverview Define the cursor which limits the number of tokens. * @author Toru Nagashima @@ -99207,7 +108736,7 @@ module.exports = function (_DecorativeCursor) { return LimitCursor; }(DecorativeCursor); -},{"./decorative-cursor":392}],398:[function(require,module,exports){ +},{"./decorative-cursor":394}],400:[function(require,module,exports){ /** * @fileoverview Define the cursor which iterates tokens only, with inflated range. * @author Toru Nagashima @@ -99260,7 +108789,7 @@ module.exports = function (_ForwardTokenCursor) { return PaddedTokenCursor; }(ForwardTokenCursor); -},{"./forward-token-cursor":395}],399:[function(require,module,exports){ +},{"./forward-token-cursor":397}],401:[function(require,module,exports){ /** * @fileoverview Define the cursor which ignores the first few tokens. * @author Toru Nagashima @@ -99326,7 +108855,7 @@ module.exports = function (_DecorativeCursor) { return SkipCursor; }(DecorativeCursor); -},{"./decorative-cursor":392}],400:[function(require,module,exports){ +},{"./decorative-cursor":394}],402:[function(require,module,exports){ /** * @fileoverview Define utilify functions for token store. * @author Toru Nagashima @@ -99428,7 +108957,7 @@ exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) { return tokens.length - 1; }; -},{"lodash":89}],401:[function(require,module,exports){ +},{"lodash":92}],403:[function(require,module,exports){ /** * @fileoverview The instance of Ajv validator. * @author Evgeny Poberezkin @@ -99450,7 +108979,8 @@ var ajv = new Ajv({ meta: false, validateSchema: false, missingRefs: "ignore", - verbose: true + verbose: true, + schemaId: "auto" }); ajv.addMetaSchema(metaSchema); @@ -99459,7 +108989,7 @@ ajv._opts.defaultMeta = metaSchema.id; module.exports = ajv; -},{"ajv":7,"ajv/lib/refs/json-schema-draft-04.json":45}],402:[function(require,module,exports){ +},{"ajv":4,"ajv/lib/refs/json-schema-draft-04.json":44}],404:[function(require,module,exports){ /** * @fileoverview A module that filters reported problems based on `eslint-disable` and `eslint-enable` comments * @author Teddy Katz @@ -99573,7 +109103,6 @@ function applyDirectives(options) { line: directive.unprocessedDirective.line, column: directive.unprocessedDirective.column, severity: 2, - source: null, nodeType: null }; }); @@ -99629,7 +109158,1480 @@ module.exports = function (options) { return options.reportUnusedDisableDirectives ? lineDirectivesResult.problems.concat(blockDirectivesResult.unusedDisableDirectives).concat(lineDirectivesResult.unusedDisableDirectives).sort(compareLocations) : lineDirectivesResult.problems; }; -},{"lodash":89}],403:[function(require,module,exports){ +},{"lodash":92}],405:[function(require,module,exports){ +/** + * @fileoverview Common utils for AST. + * @author Gyandeep Singh + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var esutils = require("esutils"); +var espree = require("espree"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +var anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/; +var anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/; +var arrayOrTypedArrayPattern = /Array$/; +var arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/; +var bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/; +var breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/; +var thisTagPattern = /^[\s*]*@this/m; + +var COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/; +var LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]); +var LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/; +var SHEBANG_MATCHER = /^#!([^\r\n]+)/; + +// A set of node types that can contain a list of statements +var STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]); + +/** + * Checks reference if is non initializer and writable. + * @param {Reference} reference - A reference to check. + * @param {int} index - The index of the reference in the references. + * @param {Reference[]} references - The array that the reference belongs to. + * @returns {boolean} Success/Failure + * @private + */ +function isModifyingReference(reference, index, references) { + var identifier = reference.identifier; + + /* + * Destructuring assignments can have multiple default value, so + * possibly there are multiple writeable references for the same + * identifier. + */ + var modifyingDifferentIdentifier = index === 0 || references[index - 1].identifier !== identifier; + + return identifier && reference.init === false && reference.isWrite() && modifyingDifferentIdentifier; +} + +/** + * Checks whether the given string starts with uppercase or not. + * + * @param {string} s - The string to check. + * @returns {boolean} `true` if the string starts with uppercase. + */ +function startsWithUpperCase(s) { + return s[0] !== s[0].toLocaleLowerCase(); +} + +/** + * Checks whether or not a node is a constructor. + * @param {ASTNode} node - A function node to check. + * @returns {boolean} Wehether or not a node is a constructor. + */ +function isES5Constructor(node) { + return node.id && startsWithUpperCase(node.id.name); +} + +/** + * Finds a function node from ancestors of a node. + * @param {ASTNode} node - A start node to find. + * @returns {Node|null} A found function node. + */ +function getUpperFunction(node) { + for (var currentNode = node; currentNode; currentNode = currentNode.parent) { + if (anyFunctionPattern.test(currentNode.type)) { + return currentNode; + } + } + return null; +} + +/** + * Checks whether a given node is a function node or not. + * The following types are function nodes: + * + * - ArrowFunctionExpression + * - FunctionDeclaration + * - FunctionExpression + * + * @param {ASTNode|null} node - A node to check. + * @returns {boolean} `true` if the node is a function node. + */ +function isFunction(node) { + return Boolean(node && anyFunctionPattern.test(node.type)); +} + +/** + * Checks whether a given node is a loop node or not. + * The following types are loop nodes: + * + * - DoWhileStatement + * - ForInStatement + * - ForOfStatement + * - ForStatement + * - WhileStatement + * + * @param {ASTNode|null} node - A node to check. + * @returns {boolean} `true` if the node is a loop node. + */ +function isLoop(node) { + return Boolean(node && anyLoopPattern.test(node.type)); +} + +/** + * Checks whether the given node is in a loop or not. + * + * @param {ASTNode} node - The node to check. + * @returns {boolean} `true` if the node is in a loop. + */ +function isInLoop(node) { + for (var currentNode = node; currentNode && !isFunction(currentNode); currentNode = currentNode.parent) { + if (isLoop(currentNode)) { + return true; + } + } + + return false; +} + +/** + * Checks whether or not a node is `null` or `undefined`. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a `null` or `undefined`. + * @public + */ +function isNullOrUndefined(node) { + return module.exports.isNullLiteral(node) || node.type === "Identifier" && node.name === "undefined" || node.type === "UnaryExpression" && node.operator === "void"; +} + +/** + * Checks whether or not a node is callee. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is callee. + */ +function isCallee(node) { + return node.parent.type === "CallExpression" && node.parent.callee === node; +} + +/** + * Checks whether or not a node is `Reflect.apply`. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a `Reflect.apply`. + */ +function isReflectApply(node) { + return node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === "Reflect" && node.property.type === "Identifier" && node.property.name === "apply" && node.computed === false; +} + +/** + * Checks whether or not a node is `Array.from`. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a `Array.from`. + */ +function isArrayFromMethod(node) { + return node.type === "MemberExpression" && node.object.type === "Identifier" && arrayOrTypedArrayPattern.test(node.object.name) && node.property.type === "Identifier" && node.property.name === "from" && node.computed === false; +} + +/** + * Checks whether or not a node is a method which has `thisArg`. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a method which has `thisArg`. + */ +function isMethodWhichHasThisArg(node) { + for (var currentNode = node; currentNode.type === "MemberExpression" && !currentNode.computed; currentNode = currentNode.property) { + if (currentNode.property.type === "Identifier") { + return arrayMethodPattern.test(currentNode.property.name); + } + } + + return false; +} + +/** + * Creates the negate function of the given function. + * @param {Function} f - The function to negate. + * @returns {Function} Negated function. + */ +function negate(f) { + return function (token) { + return !f(token); + }; +} + +/** + * Checks whether or not a node has a `@this` tag in its comments. + * @param {ASTNode} node - A node to check. + * @param {SourceCode} sourceCode - A SourceCode instance to get comments. + * @returns {boolean} Whether or not the node has a `@this` tag in its comments. + */ +function hasJSDocThisTag(node, sourceCode) { + var jsdocComment = sourceCode.getJSDocComment(node); + + if (jsdocComment && thisTagPattern.test(jsdocComment.value)) { + return true; + } + + // Checks `@this` in its leading comments for callbacks, + // because callbacks don't have its JSDoc comment. + // e.g. + // sinon.test(/* @this sinon.Sandbox */function() { this.spy(); }); + return sourceCode.getCommentsBefore(node).some(function (comment) { + return thisTagPattern.test(comment.value); + }); +} + +/** + * Determines if a node is surrounded by parentheses. + * @param {SourceCode} sourceCode The ESLint source code object + * @param {ASTNode} node The node to be checked. + * @returns {boolean} True if the node is parenthesised. + * @private + */ +function isParenthesised(sourceCode, node) { + var previousToken = sourceCode.getTokenBefore(node), + nextToken = sourceCode.getTokenAfter(node); + + return Boolean(previousToken && nextToken) && previousToken.value === "(" && previousToken.range[1] <= node.range[0] && nextToken.value === ")" && nextToken.range[0] >= node.range[1]; +} + +/** + * Checks if the given token is an arrow token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an arrow token. + */ +function isArrowToken(token) { + return token.value === "=>" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a comma token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a comma token. + */ +function isCommaToken(token) { + return token.value === "," && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a semicolon token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a semicolon token. + */ +function isSemicolonToken(token) { + return token.value === ";" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a colon token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a colon token. + */ +function isColonToken(token) { + return token.value === ":" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is an opening parenthesis token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening parenthesis token. + */ +function isOpeningParenToken(token) { + return token.value === "(" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a closing parenthesis token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing parenthesis token. + */ +function isClosingParenToken(token) { + return token.value === ")" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is an opening square bracket token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening square bracket token. + */ +function isOpeningBracketToken(token) { + return token.value === "[" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a closing square bracket token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing square bracket token. + */ +function isClosingBracketToken(token) { + return token.value === "]" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is an opening brace token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening brace token. + */ +function isOpeningBraceToken(token) { + return token.value === "{" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a closing brace token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing brace token. + */ +function isClosingBraceToken(token) { + return token.value === "}" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a comment token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a comment token. + */ +function isCommentToken(token) { + return token.type === "Line" || token.type === "Block" || token.type === "Shebang"; +} + +/** + * Checks if the given token is a keyword token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a keyword token. + */ +function isKeywordToken(token) { + return token.type === "Keyword"; +} + +/** + * Gets the `(` token of the given function node. + * + * @param {ASTNode} node - The function node to get. + * @param {SourceCode} sourceCode - The source code object to get tokens. + * @returns {Token} `(` token. + */ +function getOpeningParenOfParams(node, sourceCode) { + return node.id ? sourceCode.getTokenAfter(node.id, isOpeningParenToken) : sourceCode.getFirstToken(node, isOpeningParenToken); +} + +/** + * Creates a version of the LINEBREAK_MATCHER regex with the global flag. + * Global regexes are mutable, so this needs to be a function instead of a constant. + * @returns {RegExp} A global regular expression that matches line terminators + */ +function createGlobalLinebreakMatcher() { + return new RegExp(LINEBREAK_MATCHER.source, "g"); +} + +/** + * Checks whether or not the tokens of two given nodes are same. + * @param {ASTNode} left - A node 1 to compare. + * @param {ASTNode} right - A node 2 to compare. + * @param {SourceCode} sourceCode - The ESLint source code object. + * @returns {boolean} the source code for the given node. + */ +function equalTokens(left, right, sourceCode) { + var tokensL = sourceCode.getTokens(left); + var tokensR = sourceCode.getTokens(right); + + if (tokensL.length !== tokensR.length) { + return false; + } + for (var i = 0; i < tokensL.length; ++i) { + if (tokensL[i].type !== tokensR[i].type || tokensL[i].value !== tokensR[i].value) { + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +module.exports = { + COMMENTS_IGNORE_PATTERN: COMMENTS_IGNORE_PATTERN, + LINEBREAKS: LINEBREAKS, + LINEBREAK_MATCHER: LINEBREAK_MATCHER, + SHEBANG_MATCHER: SHEBANG_MATCHER, + STATEMENT_LIST_PARENTS: STATEMENT_LIST_PARENTS, + + /** + * Determines whether two adjacent tokens are on the same line. + * @param {Object} left - The left token object. + * @param {Object} right - The right token object. + * @returns {boolean} Whether or not the tokens are on the same line. + * @public + */ + isTokenOnSameLine: function isTokenOnSameLine(left, right) { + return left.loc.end.line === right.loc.start.line; + }, + + + isNullOrUndefined: isNullOrUndefined, + isCallee: isCallee, + isES5Constructor: isES5Constructor, + getUpperFunction: getUpperFunction, + isFunction: isFunction, + isLoop: isLoop, + isInLoop: isInLoop, + isArrayFromMethod: isArrayFromMethod, + isParenthesised: isParenthesised, + createGlobalLinebreakMatcher: createGlobalLinebreakMatcher, + equalTokens: equalTokens, + + isArrowToken: isArrowToken, + isClosingBraceToken: isClosingBraceToken, + isClosingBracketToken: isClosingBracketToken, + isClosingParenToken: isClosingParenToken, + isColonToken: isColonToken, + isCommaToken: isCommaToken, + isCommentToken: isCommentToken, + isKeywordToken: isKeywordToken, + isNotClosingBraceToken: negate(isClosingBraceToken), + isNotClosingBracketToken: negate(isClosingBracketToken), + isNotClosingParenToken: negate(isClosingParenToken), + isNotColonToken: negate(isColonToken), + isNotCommaToken: negate(isCommaToken), + isNotOpeningBraceToken: negate(isOpeningBraceToken), + isNotOpeningBracketToken: negate(isOpeningBracketToken), + isNotOpeningParenToken: negate(isOpeningParenToken), + isNotSemicolonToken: negate(isSemicolonToken), + isOpeningBraceToken: isOpeningBraceToken, + isOpeningBracketToken: isOpeningBracketToken, + isOpeningParenToken: isOpeningParenToken, + isSemicolonToken: isSemicolonToken, + + /** + * Checks whether or not a given node is a string literal. + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node is a string literal. + */ + isStringLiteral: function isStringLiteral(node) { + return node.type === "Literal" && typeof node.value === "string" || node.type === "TemplateLiteral"; + }, + + + /** + * Checks whether a given node is a breakable statement or not. + * The node is breakable if the node is one of the following type: + * + * - DoWhileStatement + * - ForInStatement + * - ForOfStatement + * - ForStatement + * - SwitchStatement + * - WhileStatement + * + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node is breakable. + */ + isBreakableStatement: function isBreakableStatement(node) { + return breakableTypePattern.test(node.type); + }, + + + /** + * Gets the label if the parent node of a given node is a LabeledStatement. + * + * @param {ASTNode} node - A node to get. + * @returns {string|null} The label or `null`. + */ + getLabel: function getLabel(node) { + if (node.parent.type === "LabeledStatement") { + return node.parent.label.name; + } + return null; + }, + + + /** + * Gets references which are non initializer and writable. + * @param {Reference[]} references - An array of references. + * @returns {Reference[]} An array of only references which are non initializer and writable. + * @public + */ + getModifyingReferences: function getModifyingReferences(references) { + return references.filter(isModifyingReference); + }, + + + /** + * Validate that a string passed in is surrounded by the specified character + * @param {string} val The text to check. + * @param {string} character The character to see if it's surrounded by. + * @returns {boolean} True if the text is surrounded by the character, false if not. + * @private + */ + isSurroundedBy: function isSurroundedBy(val, character) { + return val[0] === character && val[val.length - 1] === character; + }, + + + /** + * Returns whether the provided node is an ESLint directive comment or not + * @param {Line|Block} node The comment token to be checked + * @returns {boolean} `true` if the node is an ESLint directive comment + */ + isDirectiveComment: function isDirectiveComment(node) { + var comment = node.value.trim(); + + return node.type === "Line" && comment.indexOf("eslint-") === 0 || node.type === "Block" && (comment.indexOf("global ") === 0 || comment.indexOf("eslint ") === 0 || comment.indexOf("eslint-") === 0); + }, + + + /** + * Gets the trailing statement of a given node. + * + * if (code) + * consequent; + * + * When taking this `IfStatement`, returns `consequent;` statement. + * + * @param {ASTNode} A node to get. + * @returns {ASTNode|null} The trailing statement's node. + */ + getTrailingStatement: esutils.ast.trailingStatement, + + /** + * Finds the variable by a given name in a given scope and its upper scopes. + * + * @param {eslint-scope.Scope} initScope - A scope to start find. + * @param {string} name - A variable name to find. + * @returns {eslint-scope.Variable|null} A found variable or `null`. + */ + getVariableByName: function getVariableByName(initScope, name) { + var scope = initScope; + + while (scope) { + var variable = scope.set.get(name); + + if (variable) { + return variable; + } + + scope = scope.upper; + } + + return null; + }, + + + /** + * Checks whether or not a given function node is the default `this` binding. + * + * First, this checks the node: + * + * - The function name does not start with uppercase (it's a constructor). + * - The function does not have a JSDoc comment that has a @this tag. + * + * Next, this checks the location of the node. + * If the location is below, this judges `this` is valid. + * + * - The location is not on an object literal. + * - The location is not assigned to a variable which starts with an uppercase letter. + * - The location is not on an ES2015 class. + * - Its `bind`/`call`/`apply` method is not called directly. + * - The function is not a callback of array methods (such as `.forEach()`) if `thisArg` is given. + * + * @param {ASTNode} node - A function node to check. + * @param {SourceCode} sourceCode - A SourceCode instance to get comments. + * @returns {boolean} The function node is the default `this` binding. + */ + isDefaultThisBinding: function isDefaultThisBinding(node, sourceCode) { + if (isES5Constructor(node) || hasJSDocThisTag(node, sourceCode)) { + return false; + } + var isAnonymous = node.id === null; + var currentNode = node; + + while (currentNode) { + var parent = currentNode.parent; + + switch (parent.type) { + + /* + * Looks up the destination. + * e.g., obj.foo = nativeFoo || function foo() { ... }; + */ + case "LogicalExpression": + case "ConditionalExpression": + currentNode = parent; + break; + + /* + * If the upper function is IIFE, checks the destination of the return value. + * e.g. + * obj.foo = (function() { + * // setup... + * return function foo() { ... }; + * })(); + * obj.foo = (() => + * function foo() { ... } + * )(); + */ + case "ReturnStatement": + { + var func = getUpperFunction(parent); + + if (func === null || !isCallee(func)) { + return true; + } + currentNode = func.parent; + break; + } + case "ArrowFunctionExpression": + if (currentNode !== parent.body || !isCallee(parent)) { + return true; + } + currentNode = parent.parent; + break; + + /* + * e.g. + * var obj = { foo() { ... } }; + * var obj = { foo: function() { ... } }; + * class A { constructor() { ... } } + * class A { foo() { ... } } + * class A { get foo() { ... } } + * class A { set foo() { ... } } + * class A { static foo() { ... } } + */ + case "Property": + case "MethodDefinition": + return parent.value !== currentNode; + + /* + * e.g. + * obj.foo = function foo() { ... }; + * Foo = function() { ... }; + * [obj.foo = function foo() { ... }] = a; + * [Foo = function() { ... }] = a; + */ + case "AssignmentExpression": + case "AssignmentPattern": + if (parent.left.type === "MemberExpression") { + return false; + } + if (isAnonymous && parent.left.type === "Identifier" && startsWithUpperCase(parent.left.name)) { + return false; + } + return true; + + /* + * e.g. + * var Foo = function() { ... }; + */ + case "VariableDeclarator": + return !(isAnonymous && parent.init === currentNode && parent.id.type === "Identifier" && startsWithUpperCase(parent.id.name)); + + /* + * e.g. + * var foo = function foo() { ... }.bind(obj); + * (function foo() { ... }).call(obj); + * (function foo() { ... }).apply(obj, []); + */ + case "MemberExpression": + return parent.object !== currentNode || parent.property.type !== "Identifier" || !bindOrCallOrApplyPattern.test(parent.property.name) || !isCallee(parent) || parent.parent.arguments.length === 0 || isNullOrUndefined(parent.parent.arguments[0]); + + /* + * e.g. + * Reflect.apply(function() {}, obj, []); + * Array.from([], function() {}, obj); + * list.forEach(function() {}, obj); + */ + case "CallExpression": + if (isReflectApply(parent.callee)) { + return parent.arguments.length !== 3 || parent.arguments[0] !== currentNode || isNullOrUndefined(parent.arguments[1]); + } + if (isArrayFromMethod(parent.callee)) { + return parent.arguments.length !== 3 || parent.arguments[1] !== currentNode || isNullOrUndefined(parent.arguments[2]); + } + if (isMethodWhichHasThisArg(parent.callee)) { + return parent.arguments.length !== 2 || parent.arguments[0] !== currentNode || isNullOrUndefined(parent.arguments[1]); + } + return true; + + // Otherwise `this` is default. + default: + return true; + } + } + + /* istanbul ignore next */ + return true; + }, + + + /** + * Get the precedence level based on the node type + * @param {ASTNode} node node to evaluate + * @returns {int} precedence level + * @private + */ + getPrecedence: function getPrecedence(node) { + switch (node.type) { + case "SequenceExpression": + return 0; + + case "AssignmentExpression": + case "ArrowFunctionExpression": + case "YieldExpression": + return 1; + + case "ConditionalExpression": + return 3; + + case "LogicalExpression": + switch (node.operator) { + case "||": + return 4; + case "&&": + return 5; + + // no default + } + + /* falls through */ + + case "BinaryExpression": + + switch (node.operator) { + case "|": + return 6; + case "^": + return 7; + case "&": + return 8; + case "==": + case "!=": + case "===": + case "!==": + return 9; + case "<": + case "<=": + case ">": + case ">=": + case "in": + case "instanceof": + return 10; + case "<<": + case ">>": + case ">>>": + return 11; + case "+": + case "-": + return 12; + case "*": + case "/": + case "%": + return 13; + case "**": + return 15; + + // no default + } + + /* falls through */ + + case "UnaryExpression": + case "AwaitExpression": + return 16; + + case "UpdateExpression": + return 17; + + case "CallExpression": + return 18; + + case "NewExpression": + return 19; + + default: + return 20; + } + }, + + + /** + * Checks whether the given node is an empty block node or not. + * + * @param {ASTNode|null} node - The node to check. + * @returns {boolean} `true` if the node is an empty block. + */ + isEmptyBlock: function isEmptyBlock(node) { + return Boolean(node && node.type === "BlockStatement" && node.body.length === 0); + }, + + + /** + * Checks whether the given node is an empty function node or not. + * + * @param {ASTNode|null} node - The node to check. + * @returns {boolean} `true` if the node is an empty function. + */ + isEmptyFunction: function isEmptyFunction(node) { + return isFunction(node) && module.exports.isEmptyBlock(node.body); + }, + + + /** + * Gets the property name of a given node. + * The node can be a MemberExpression, a Property, or a MethodDefinition. + * + * If the name is dynamic, this returns `null`. + * + * For examples: + * + * a.b // => "b" + * a["b"] // => "b" + * a['b'] // => "b" + * a[`b`] // => "b" + * a[100] // => "100" + * a[b] // => null + * a["a" + "b"] // => null + * a[tag`b`] // => null + * a[`${b}`] // => null + * + * let a = {b: 1} // => "b" + * let a = {["b"]: 1} // => "b" + * let a = {['b']: 1} // => "b" + * let a = {[`b`]: 1} // => "b" + * let a = {[100]: 1} // => "100" + * let a = {[b]: 1} // => null + * let a = {["a" + "b"]: 1} // => null + * let a = {[tag`b`]: 1} // => null + * let a = {[`${b}`]: 1} // => null + * + * @param {ASTNode} node - The node to get. + * @returns {string|null} The property name if static. Otherwise, null. + */ + getStaticPropertyName: function getStaticPropertyName(node) { + var prop = void 0; + + switch (node && node.type) { + case "Property": + case "MethodDefinition": + prop = node.key; + break; + + case "MemberExpression": + prop = node.property; + break; + + // no default + } + + switch (prop && prop.type) { + case "Literal": + return String(prop.value); + + case "TemplateLiteral": + if (prop.expressions.length === 0 && prop.quasis.length === 1) { + return prop.quasis[0].value.cooked; + } + break; + + case "Identifier": + if (!node.computed) { + return prop.name; + } + break; + + // no default + } + + return null; + }, + + + /** + * Get directives from directive prologue of a Program or Function node. + * @param {ASTNode} node - The node to check. + * @returns {ASTNode[]} The directives found in the directive prologue. + */ + getDirectivePrologue: function getDirectivePrologue(node) { + var directives = []; + + // Directive prologues only occur at the top of files or functions. + if (node.type === "Program" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || + + /* + * Do not check arrow functions with implicit return. + * `() => "use strict";` returns the string `"use strict"`. + */ + node.type === "ArrowFunctionExpression" && node.body.type === "BlockStatement") { + var statements = node.type === "Program" ? node.body : node.body.body; + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = statements[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var statement = _step.value; + + if (statement.type === "ExpressionStatement" && statement.expression.type === "Literal") { + directives.push(statement); + } else { + break; + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + + return directives; + }, + + + /** + * Determines whether this node is a decimal integer literal. If a node is a decimal integer literal, a dot added + * after the node will be parsed as a decimal point, rather than a property-access dot. + * @param {ASTNode} node - The node to check. + * @returns {boolean} `true` if this node is a decimal integer. + * @example + * + * 5 // true + * 5. // false + * 5.0 // false + * 05 // false + * 0x5 // false + * 0b101 // false + * 0o5 // false + * 5e0 // false + * '5' // false + */ + isDecimalInteger: function isDecimalInteger(node) { + return node.type === "Literal" && typeof node.value === "number" && /^(0|[1-9]\d*)$/.test(node.raw); + }, + + + /** + * Gets the name and kind of the given function node. + * + * - `function foo() {}` .................... `function 'foo'` + * - `(function foo() {})` .................. `function 'foo'` + * - `(function() {})` ...................... `function` + * - `function* foo() {}` ................... `generator function 'foo'` + * - `(function* foo() {})` ................. `generator function 'foo'` + * - `(function*() {})` ..................... `generator function` + * - `() => {}` ............................. `arrow function` + * - `async () => {}` ....................... `async arrow function` + * - `({ foo: function foo() {} })` ......... `method 'foo'` + * - `({ foo: function() {} })` ............. `method 'foo'` + * - `({ ['foo']: function() {} })` ......... `method 'foo'` + * - `({ [foo]: function() {} })` ........... `method` + * - `({ foo() {} })` ....................... `method 'foo'` + * - `({ foo: function* foo() {} })` ........ `generator method 'foo'` + * - `({ foo: function*() {} })` ............ `generator method 'foo'` + * - `({ ['foo']: function*() {} })` ........ `generator method 'foo'` + * - `({ [foo]: function*() {} })` .......... `generator method` + * - `({ *foo() {} })` ...................... `generator method 'foo'` + * - `({ foo: async function foo() {} })` ... `async method 'foo'` + * - `({ foo: async function() {} })` ....... `async method 'foo'` + * - `({ ['foo']: async function() {} })` ... `async method 'foo'` + * - `({ [foo]: async function() {} })` ..... `async method` + * - `({ async foo() {} })` ................. `async method 'foo'` + * - `({ get foo() {} })` ................... `getter 'foo'` + * - `({ set foo(a) {} })` .................. `setter 'foo'` + * - `class A { constructor() {} }` ......... `constructor` + * - `class A { foo() {} }` ................. `method 'foo'` + * - `class A { *foo() {} }` ................ `generator method 'foo'` + * - `class A { async foo() {} }` ........... `async method 'foo'` + * - `class A { ['foo']() {} }` ............. `method 'foo'` + * - `class A { *['foo']() {} }` ............ `generator method 'foo'` + * - `class A { async ['foo']() {} }` ....... `async method 'foo'` + * - `class A { [foo]() {} }` ............... `method` + * - `class A { *[foo]() {} }` .............. `generator method` + * - `class A { async [foo]() {} }` ......... `async method` + * - `class A { get foo() {} }` ............. `getter 'foo'` + * - `class A { set foo(a) {} }` ............ `setter 'foo'` + * - `class A { static foo() {} }` .......... `static method 'foo'` + * - `class A { static *foo() {} }` ......... `static generator method 'foo'` + * - `class A { static async foo() {} }` .... `static async method 'foo'` + * - `class A { static get foo() {} }` ...... `static getter 'foo'` + * - `class A { static set foo(a) {} }` ..... `static setter 'foo'` + * + * @param {ASTNode} node - The function node to get. + * @returns {string} The name and kind of the function node. + */ + getFunctionNameWithKind: function getFunctionNameWithKind(node) { + var parent = node.parent; + var tokens = []; + + if (parent.type === "MethodDefinition" && parent.static) { + tokens.push("static"); + } + if (node.async) { + tokens.push("async"); + } + if (node.generator) { + tokens.push("generator"); + } + + if (node.type === "ArrowFunctionExpression") { + tokens.push("arrow", "function"); + } else if (parent.type === "Property" || parent.type === "MethodDefinition") { + if (parent.kind === "constructor") { + return "constructor"; + } + if (parent.kind === "get") { + tokens.push("getter"); + } else if (parent.kind === "set") { + tokens.push("setter"); + } else { + tokens.push("method"); + } + } else { + tokens.push("function"); + } + + if (node.id) { + tokens.push("'" + node.id.name + "'"); + } else { + var name = module.exports.getStaticPropertyName(parent); + + if (name) { + tokens.push("'" + name + "'"); + } + } + + return tokens.join(" "); + }, + + + /** + * Gets the location of the given function node for reporting. + * + * - `function foo() {}` + * ^^^^^^^^^^^^ + * - `(function foo() {})` + * ^^^^^^^^^^^^ + * - `(function() {})` + * ^^^^^^^^ + * - `function* foo() {}` + * ^^^^^^^^^^^^^ + * - `(function* foo() {})` + * ^^^^^^^^^^^^^ + * - `(function*() {})` + * ^^^^^^^^^ + * - `() => {}` + * ^^ + * - `async () => {}` + * ^^ + * - `({ foo: function foo() {} })` + * ^^^^^^^^^^^^^^^^^ + * - `({ foo: function() {} })` + * ^^^^^^^^^^^^^ + * - `({ ['foo']: function() {} })` + * ^^^^^^^^^^^^^^^^^ + * - `({ [foo]: function() {} })` + * ^^^^^^^^^^^^^^^ + * - `({ foo() {} })` + * ^^^ + * - `({ foo: function* foo() {} })` + * ^^^^^^^^^^^^^^^^^^ + * - `({ foo: function*() {} })` + * ^^^^^^^^^^^^^^ + * - `({ ['foo']: function*() {} })` + * ^^^^^^^^^^^^^^^^^^ + * - `({ [foo]: function*() {} })` + * ^^^^^^^^^^^^^^^^ + * - `({ *foo() {} })` + * ^^^^ + * - `({ foo: async function foo() {} })` + * ^^^^^^^^^^^^^^^^^^^^^^^ + * - `({ foo: async function() {} })` + * ^^^^^^^^^^^^^^^^^^^ + * - `({ ['foo']: async function() {} })` + * ^^^^^^^^^^^^^^^^^^^^^^^ + * - `({ [foo]: async function() {} })` + * ^^^^^^^^^^^^^^^^^^^^^ + * - `({ async foo() {} })` + * ^^^^^^^^^ + * - `({ get foo() {} })` + * ^^^^^^^ + * - `({ set foo(a) {} })` + * ^^^^^^^ + * - `class A { constructor() {} }` + * ^^^^^^^^^^^ + * - `class A { foo() {} }` + * ^^^ + * - `class A { *foo() {} }` + * ^^^^ + * - `class A { async foo() {} }` + * ^^^^^^^^^ + * - `class A { ['foo']() {} }` + * ^^^^^^^ + * - `class A { *['foo']() {} }` + * ^^^^^^^^ + * - `class A { async ['foo']() {} }` + * ^^^^^^^^^^^^^ + * - `class A { [foo]() {} }` + * ^^^^^ + * - `class A { *[foo]() {} }` + * ^^^^^^ + * - `class A { async [foo]() {} }` + * ^^^^^^^^^^^ + * - `class A { get foo() {} }` + * ^^^^^^^ + * - `class A { set foo(a) {} }` + * ^^^^^^^ + * - `class A { static foo() {} }` + * ^^^^^^^^^^ + * - `class A { static *foo() {} }` + * ^^^^^^^^^^^ + * - `class A { static async foo() {} }` + * ^^^^^^^^^^^^^^^^ + * - `class A { static get foo() {} }` + * ^^^^^^^^^^^^^^ + * - `class A { static set foo(a) {} }` + * ^^^^^^^^^^^^^^ + * + * @param {ASTNode} node - The function node to get. + * @param {SourceCode} sourceCode - The source code object to get tokens. + * @returns {string} The location of the function node for reporting. + */ + getFunctionHeadLoc: function getFunctionHeadLoc(node, sourceCode) { + var parent = node.parent; + var start = null; + var end = null; + + if (node.type === "ArrowFunctionExpression") { + var arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken); + + start = arrowToken.loc.start; + end = arrowToken.loc.end; + } else if (parent.type === "Property" || parent.type === "MethodDefinition") { + start = parent.loc.start; + end = getOpeningParenOfParams(node, sourceCode).loc.start; + } else { + start = node.loc.start; + end = getOpeningParenOfParams(node, sourceCode).loc.start; + } + + return { + start: Object.assign({}, start), + end: Object.assign({}, end) + }; + }, + + + /** + * Gets the parenthesized text of a node. This is similar to sourceCode.getText(node), but it also includes any parentheses + * surrounding the node. + * @param {SourceCode} sourceCode The source code object + * @param {ASTNode} node An expression node + * @returns {string} The text representing the node, with all surrounding parentheses included + */ + getParenthesisedText: function getParenthesisedText(sourceCode, node) { + var leftToken = sourceCode.getFirstToken(node); + var rightToken = sourceCode.getLastToken(node); + + while (sourceCode.getTokenBefore(leftToken) && sourceCode.getTokenBefore(leftToken).type === "Punctuator" && sourceCode.getTokenBefore(leftToken).value === "(" && sourceCode.getTokenAfter(rightToken) && sourceCode.getTokenAfter(rightToken).type === "Punctuator" && sourceCode.getTokenAfter(rightToken).value === ")") { + leftToken = sourceCode.getTokenBefore(leftToken); + rightToken = sourceCode.getTokenAfter(rightToken); + } + + return sourceCode.getText().slice(leftToken.range[0], rightToken.range[1]); + }, + + + /* + * Determine if a node has a possiblity to be an Error object + * @param {ASTNode} node ASTNode to check + * @returns {boolean} True if there is a chance it contains an Error obj + */ + couldBeError: function couldBeError(node) { + switch (node.type) { + case "Identifier": + case "CallExpression": + case "NewExpression": + case "MemberExpression": + case "TaggedTemplateExpression": + case "YieldExpression": + case "AwaitExpression": + return true; // possibly an error object. + + case "AssignmentExpression": + return module.exports.couldBeError(node.right); + + case "SequenceExpression": + { + var exprs = node.expressions; + + return exprs.length !== 0 && module.exports.couldBeError(exprs[exprs.length - 1]); + } + + case "LogicalExpression": + return module.exports.couldBeError(node.left) || module.exports.couldBeError(node.right); + + case "ConditionalExpression": + return module.exports.couldBeError(node.consequent) || module.exports.couldBeError(node.alternate); + + default: + return false; + } + }, + + + /** + * Determines whether the given node is a `null` literal. + * @param {ASTNode} node The node to check + * @returns {boolean} `true` if the node is a `null` literal + */ + isNullLiteral: function isNullLiteral(node) { + + /* + * Checking `node.value === null` does not guarantee that a literal is a null literal. + * When parsing values that cannot be represented in the current environment (e.g. unicode + * regexes in Node 4), `node.value` is set to `null` because it wouldn't be possible to + * set `node.value` to a unicode regex. To make sure a literal is actually `null`, check + * `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020 + */ + return node.type === "Literal" && node.value === null && !node.regex; + }, + + + /** + * Determines whether two tokens can safely be placed next to each other without merging into a single token + * @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used. + * @param {Token|string} rightValue The right token. If this is a string, it will be tokenized and the first token will be used. + * @returns {boolean} If the tokens cannot be safely placed next to each other, returns `false`. If the tokens can be placed + * next to each other, behavior is undefined (although it should return `true` in most cases). + */ + canTokensBeAdjacent: function canTokensBeAdjacent(leftValue, rightValue) { + var leftToken = void 0; + + if (typeof leftValue === "string") { + var leftTokens = espree.tokenize(leftValue, { ecmaVersion: 2015 }); + + leftToken = leftTokens[leftTokens.length - 1]; + } else { + leftToken = leftValue; + } + + var rightToken = typeof rightValue === "string" ? espree.tokenize(rightValue, { ecmaVersion: 2015 })[0] : rightValue; + + if (leftToken.type === "Punctuator" || rightToken.type === "Punctuator") { + if (leftToken.type === "Punctuator" && rightToken.type === "Punctuator") { + var PLUS_TOKENS = new Set(["+", "++"]); + var MINUS_TOKENS = new Set(["-", "--"]); + + return !(PLUS_TOKENS.has(leftToken.value) && PLUS_TOKENS.has(rightToken.value) || MINUS_TOKENS.has(leftToken.value) && MINUS_TOKENS.has(rightToken.value)); + } + return true; + } + + if (leftToken.type === "String" || rightToken.type === "String" || leftToken.type === "Template" || rightToken.type === "Template") { + return true; + } + + if (leftToken.type !== "Numeric" && rightToken.type === "Numeric" && rightToken.value.startsWith(".")) { + return true; + } + + return false; + } +}; + +},{"espree":"espree","esutils":80}],406:[function(require,module,exports){ +/** + * @fileoverview Config Comment Parser + * @author Nicholas C. Zakas + */ + +/* eslint-disable class-methods-use-this*/ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var levn = require("levn"), + ConfigOps = require("../config/config-ops"); + +var debug = require("debug")("eslint:config-comment-parser"); + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +/** + * Object to parse ESLint configuration comments inside JavaScript files. + * @name ConfigCommentParser + */ +module.exports = function () { + function ConfigCommentParser() { + _classCallCheck(this, ConfigCommentParser); + } + + _createClass(ConfigCommentParser, [{ + key: "parseBooleanConfig", + + + /** + * Parses a list of "name:boolean_value" or/and "name" options divided by comma or + * whitespace. Used for "global" and "exported" comments. + * @param {string} string The string to parse. + * @param {Comment} comment The comment node which has the string. + * @returns {Object} Result map object of names and boolean values + */ + value: function parseBooleanConfig(string, comment) { + debug("Parsing Boolean config"); + + var items = {}; + + // Collapse whitespace around `:` and `,` to make parsing easier + var trimmedString = string.replace(/\s*([:,])\s*/g, "$1"); + + trimmedString.split(/\s|,+/).forEach(function (name) { + if (!name) { + return; + } + + // value defaults to "false" (if not provided), e.g: "foo" => ["foo", "false"] + + var _name$split = name.split(":"), + _name$split2 = _slicedToArray(_name$split, 2), + key = _name$split2[0], + _name$split2$ = _name$split2[1], + value = _name$split2$ === undefined ? "false" : _name$split2$; + + items[key] = { + value: value === "true", + comment: comment + }; + }); + return items; + } + + /** + * Parses a JSON-like config. + * @param {string} string The string to parse. + * @param {Object} location Start line and column of comments for potential error message. + * @returns {({success: true, config: Object}|{success: false, error: Problem})} Result map object + */ + + }, { + key: "parseJsonConfig", + value: function parseJsonConfig(string, location) { + debug("Parsing JSON config"); + + var items = {}; + + // Parses a JSON-like comment by the same way as parsing CLI option. + try { + items = levn.parse("Object", string) || {}; + + // Some tests say that it should ignore invalid comments such as `/*eslint no-alert:abc*/`. + // Also, commaless notations have invalid severity: + // "no-alert: 2 no-console: 2" --> {"no-alert": "2 no-console: 2"} + // Should ignore that case as well. + if (ConfigOps.isEverySeverityValid(items)) { + return { + success: true, + config: items + }; + } + } catch (ex) { + + debug("Levn parsing failed; falling back to manual parsing."); + + // ignore to parse the string by a fallback. + } + + /* + * Optionator cannot parse commaless notations. + * But we are supporting that. So this is a fallback for that. + */ + items = {}; + var normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/g, "\"$1\":").replace(/(]|[0-9])\s+(?=")/, "$1,"); + + try { + items = JSON.parse("{" + normalizedString + "}"); + } catch (ex) { + debug("Manual parsing failed."); + + return { + success: false, + error: { + ruleId: null, + fatal: true, + severity: 2, + message: "Failed to parse JSON from '" + normalizedString + "': " + ex.message, + line: location.start.line, + column: location.start.column + 1 + } + }; + } + + return { + success: true, + config: items + }; + } + + /** + * Parses a config of values separated by comma. + * @param {string} string The string to parse. + * @returns {Object} Result map of values and true values + */ + + }, { + key: "parseListConfig", + value: function parseListConfig(string) { + debug("Parsing list config"); + + var items = {}; + + // Collapse whitespace around commas + string.replace(/\s*,\s*/g, ",").split(/,+/).forEach(function (name) { + var trimmedName = name.trim(); + + if (trimmedName) { + items[trimmedName] = true; + } + }); + return items; + } + }]); + + return ConfigCommentParser; +}(); + +},{"../config/config-ops":119,"debug":53,"levn":90}],407:[function(require,module,exports){ /** * @fileoverview Helper class to aid in constructing fix commands. * @author Alan Pierce @@ -99644,7 +110646,7 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var astUtils = require("../ast-utils"); +var astUtils = require("../util/ast-utils"); //------------------------------------------------------------------------------ // Public Interface @@ -99769,7 +110771,7 @@ var FixTracker = function () { module.exports = FixTracker; -},{"../ast-utils":115}],404:[function(require,module,exports){ +},{"../util/ast-utils":405}],408:[function(require,module,exports){ /** * @fileoverview Interpolate keys from an object into a string with {{ }} markers. * @author Jed Fox @@ -99785,7 +110787,11 @@ module.exports = function (text, data) { if (!data) { return text; } - return text.replace(/\{\{\s*([^{}]+?)\s*\}\}/g, function (fullMatch, term) { + + // Substitution content for any {{ }} markers. + return text.replace(/\{\{([^{}]+?)\}\}/g, function (fullMatch, termWithWhitespace) { + var term = termWithWhitespace.trim(); + if (term in data) { return data[term]; } @@ -99795,7 +110801,7 @@ module.exports = function (text, data) { }); }; -},{}],405:[function(require,module,exports){ +},{}],409:[function(require,module,exports){ /** * @fileoverview A shared list of ES3 keywords. * @author Josh Perez @@ -99804,7 +110810,7 @@ module.exports = function (text, data) { module.exports = ["abstract", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with"]; -},{}],406:[function(require,module,exports){ +},{}],410:[function(require,module,exports){ /** * @fileoverview The event generator for AST nodes. * @author Toru Nagashima @@ -99820,6 +110826,8 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + var esquery = require("esquery"); var lodash = require("lodash"); @@ -99857,10 +110865,8 @@ function getPossibleTypes(parsedSelector) { { var typesForComponents = parsedSelector.selectors.map(getPossibleTypes); - if (typesForComponents.every(function (typesForComponent) { - return typesForComponent; - })) { - return lodash.union.apply(null, typesForComponents); + if (typesForComponents.every(Boolean)) { + return lodash.union.apply(lodash, _toConsumableArray(typesForComponents)); } return null; } @@ -99880,7 +110886,7 @@ function getPossibleTypes(parsedSelector) { * If at least one of the components could only match a particular type, the compound could only match * the intersection of those types. */ - return lodash.intersection.apply(null, _typesForComponents); + return lodash.intersection.apply(lodash, _toConsumableArray(_typesForComponents)); } case "child": @@ -100147,7 +111153,7 @@ var NodeEventGenerator = function () { module.exports = NodeEventGenerator; -},{"esquery":69,"lodash":89}],407:[function(require,module,exports){ +},{"esquery":71,"lodash":92}],411:[function(require,module,exports){ /** * @fileoverview Pattern for detecting any letter (even letters outside of ASCII). * NOTE: This file was generated using this script in JSCS based on the Unicode 7.0.0 standard: https://github.com/jscs-dev/node-jscs/blob/f5ed14427deb7e7aac84f3056a5aab2d9f3e563e/publish/helpers/generate-patterns.js @@ -100185,7 +111191,313 @@ module.exports = NodeEventGenerator; module.exports = /[A-Za-z\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\u0561-\u0587\u05D0-\u05EA\u05F0-\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\u08A0-\u08B2\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\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\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\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\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-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\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\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\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\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\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-\uAB5F\uAB64\uAB65\uABC0-\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/; -},{}],408:[function(require,module,exports){ +},{}],412:[function(require,module,exports){ +/** + * @fileoverview A helper that translates context.report() calls from the rule API into generic problem objects + * @author Teddy Katz + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var assert = require("assert"); +var ruleFixer = require("./rule-fixer"); +var interpolate = require("./interpolate"); + +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** + * An error message description + * @typedef {Object} MessageDescriptor + * @property {ASTNode} [node] The reported node + * @property {Location} loc The location of the problem. + * @property {string} message The problem message. + * @property {Object} [data] Optional data to use to fill in placeholders in the + * message. + * @property {Function} [fix] The function to call that creates a fix command. + */ + +/** + * Information about the report + * @typedef {Object} ReportInfo + * @property {string} ruleId + * @property {(0|1|2)} severity + * @property {(string|undefined)} message + * @property {(string|undefined)} messageId + * @property {number} line + * @property {number} column + * @property {(number|undefined)} endLine + * @property {(number|undefined)} endColumn + * @property {(string|null)} nodeType + * @property {string} source + * @property {({text: string, range: (number[]|null)}|null)} fix + */ + +//------------------------------------------------------------------------------ +// Module Definition +//------------------------------------------------------------------------------ + + +/** + * Translates a multi-argument context.report() call into a single object argument call + * @param {...*} args A list of arguments passed to `context.report` + * @returns {MessageDescriptor} A normalized object containing report information + */ +function normalizeMultiArgReportCall() { + + // If there is one argument, it is considered to be a new-style call already. + if (arguments.length === 1) { + + // Shallow clone the object to avoid surprises if reusing the descriptor + return Object.assign({}, arguments.length <= 0 ? undefined : arguments[0]); + } + + // If the second argument is a string, the arguments are interpreted as [node, message, data, fix]. + if (typeof (arguments.length <= 1 ? undefined : arguments[1]) === "string") { + return { + node: arguments.length <= 0 ? undefined : arguments[0], + message: arguments.length <= 1 ? undefined : arguments[1], + data: arguments.length <= 2 ? undefined : arguments[2], + fix: arguments.length <= 3 ? undefined : arguments[3] + }; + } + + // Otherwise, the arguments are interpreted as [node, loc, message, data, fix]. + return { + node: arguments.length <= 0 ? undefined : arguments[0], + loc: arguments.length <= 1 ? undefined : arguments[1], + message: arguments.length <= 2 ? undefined : arguments[2], + data: arguments.length <= 3 ? undefined : arguments[3], + fix: arguments.length <= 4 ? undefined : arguments[4] + }; +} + +/** + * Asserts that either a loc or a node was provided, and the node is valid if it was provided. + * @param {MessageDescriptor} descriptor A descriptor to validate + * @returns {void} + * @throws AssertionError if neither a node nor a loc was provided, or if the node is not an object + */ +function assertValidNodeInfo(descriptor) { + if (descriptor.node) { + assert(_typeof(descriptor.node) === "object", "Node must be an object"); + } else { + assert(descriptor.loc, "Node must be provided when reporting error if location is not provided"); + } +} + +/** + * Normalizes a MessageDescriptor to always have a `loc` with `start` and `end` properties + * @param {MessageDescriptor} descriptor A descriptor for the report from a rule. + * @returns {{start: Location, end: (Location|null)}} An updated location that infers the `start` and `end` properties + * from the `node` of the original descriptor, or infers the `start` from the `loc` of the original descriptor. + */ +function normalizeReportLoc(descriptor) { + if (descriptor.loc) { + if (descriptor.loc.start) { + return descriptor.loc; + } + return { start: descriptor.loc, end: null }; + } + return descriptor.node.loc; +} + +/** + * Compares items in a fixes array by range. + * @param {Fix} a The first message. + * @param {Fix} b The second message. + * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. + * @private + */ +function compareFixesByRange(a, b) { + return a.range[0] - b.range[0] || a.range[1] - b.range[1]; +} + +/** + * Merges the given fixes array into one. + * @param {Fix[]} fixes The fixes to merge. + * @param {SourceCode} sourceCode The source code object to get the text between fixes. + * @returns {{text: string, range: number[]}} The merged fixes + */ +function mergeFixes(fixes, sourceCode) { + if (fixes.length === 0) { + return null; + } + if (fixes.length === 1) { + return fixes[0]; + } + + fixes.sort(compareFixesByRange); + + var originalText = sourceCode.text; + var start = fixes[0].range[0]; + var end = fixes[fixes.length - 1].range[1]; + var text = ""; + var lastPos = Number.MIN_SAFE_INTEGER; + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = fixes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var fix = _step.value; + + assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); + + if (fix.range[0] >= 0) { + text += originalText.slice(Math.max(0, start, lastPos), fix.range[0]); + } + text += fix.text; + lastPos = fix.range[1]; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + text += originalText.slice(Math.max(0, start, lastPos), end); + + return { range: [start, end], text: text }; +} + +/** + * Gets one fix object from the given descriptor. + * If the descriptor retrieves multiple fixes, this merges those to one. + * @param {MessageDescriptor} descriptor The report descriptor. + * @param {SourceCode} sourceCode The source code object to get text between fixes. + * @returns {({text: string, range: number[]}|null)} The fix for the descriptor + */ +function normalizeFixes(descriptor, sourceCode) { + if (typeof descriptor.fix !== "function") { + return null; + } + + // @type {null | Fix | Fix[] | IterableIterator} + var fix = descriptor.fix(ruleFixer); + + // Merge to one. + if (fix && Symbol.iterator in fix) { + return mergeFixes(Array.from(fix), sourceCode); + } + return fix; +} + +/** + * Creates information about the report from a descriptor + * @param {Object} options Information about the problem + * @param {string} options.ruleId Rule ID + * @param {(0|1|2)} options.severity Rule severity + * @param {(ASTNode|null)} options.node Node + * @param {string} options.message Error message + * @param {string} [options.messageId] The error message ID. + * @param {{start: SourceLocation, end: (SourceLocation|null)}} options.loc Start and end location + * @param {{text: string, range: (number[]|null)}} options.fix The fix object + * @returns {function(...args): ReportInfo} Function that returns information about the report + */ +function createProblem(options) { + var problem = { + ruleId: options.ruleId, + severity: options.severity, + message: options.message, + line: options.loc.start.line, + column: options.loc.start.column + 1, + nodeType: options.node && options.node.type || null + }; + + /* + * If this isn’t in the conditional, some of the tests fail + * because `messageId` is present in the problem object + */ + if (options.messageId) { + problem.messageId = options.messageId; + } + + if (options.loc.end) { + problem.endLine = options.loc.end.line; + problem.endColumn = options.loc.end.column + 1; + } + + if (options.fix) { + problem.fix = options.fix; + } + + return problem; +} + +/** + * Returns a function that converts the arguments of a `context.report` call from a rule into a reported + * problem for the Node.js API. + * @param {{ruleId: string, severity: number, sourceCode: SourceCode, messageIds: Object}} metadata Metadata for the reported problem + * @param {SourceCode} sourceCode The `SourceCode` instance for the text being linted + * @returns {function(...args): ReportInfo} Function that returns information about the report + */ + +module.exports = function createReportTranslator(metadata) { + + /* + * `createReportTranslator` gets called once per enabled rule per file. It needs to be very performant. + * The report translator itself (i.e. the function that `createReportTranslator` returns) gets + * called every time a rule reports a problem, which happens much less frequently (usually, the vast + * majority of rules don't report any problems for a given file). + */ + return function () { + var descriptor = normalizeMultiArgReportCall.apply(undefined, arguments); + + assertValidNodeInfo(descriptor); + + var computedMessage = void 0; + + if (descriptor.messageId) { + if (!metadata.messageIds) { + throw new TypeError("context.report() called with a messageId, but no messages were present in the rule metadata."); + } + var id = descriptor.messageId; + var messages = metadata.messageIds; + + if (descriptor.message) { + throw new TypeError("context.report() called with a message and a messageId. Please only pass one."); + } + if (!messages || !Object.prototype.hasOwnProperty.call(messages, id)) { + throw new TypeError("context.report() called with a messageId of '" + id + "' which is not present in the 'messages' config: " + JSON.stringify(messages, null, 2)); + } + computedMessage = messages[id]; + } else if (descriptor.message) { + computedMessage = descriptor.message; + } else { + throw new TypeError("Missing `message` property in report() call; add a message that describes the linting problem."); + } + + return createProblem({ + ruleId: metadata.ruleId, + severity: metadata.severity, + node: descriptor.node, + message: interpolate(computedMessage, descriptor.data), + messageId: descriptor.messageId, + loc: normalizeReportLoc(descriptor), + fix: normalizeFixes(descriptor, metadata.sourceCode) + }); + }; +}; + +},{"./interpolate":408,"./rule-fixer":413,"assert":46}],413:[function(require,module,exports){ /** * @fileoverview An object that creates fix commands for rules. * @author Nicholas C. Zakas @@ -100333,7 +111645,7 @@ var ruleFixer = Object.freeze({ module.exports = ruleFixer; -},{}],409:[function(require,module,exports){ +},{}],414:[function(require,module,exports){ /** * @fileoverview A variant of EventEmitter which does not give listeners information about each other * @author Teddy Katz @@ -100363,8 +111675,6 @@ module.exports = ruleFixer; * another module throws an error or registers a listener. * 2. It calls listener functions without any `this` value. (`EventEmitter` calls listeners with a * `this` value of the emitter instance, which would give listeners access to other listeners.) - * 3. Events can be emitted with at most 3 arguments. (For example: when using `emitter.emit('foo', a, b, c)`, - * the arguments `a`, `b`, and `c` will be passed to the listener functions.) * @returns {SafeEmitter} An emitter */ @@ -100379,10 +111689,14 @@ module.exports = function () { listeners[eventName] = [listener]; } }, - emit: function emit(eventName, a, b, c) { + emit: function emit(eventName) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + if (eventName in listeners) { listeners[eventName].forEach(function (listener) { - return listener(a, b, c); + return listener.apply(undefined, args); }); } }, @@ -100392,7 +111706,7 @@ module.exports = function () { }); }; -},{}],410:[function(require,module,exports){ +},{}],415:[function(require,module,exports){ /** * @fileoverview An object that caches and applies source code fixes. * @author Nicholas C. Zakas @@ -100403,7 +111717,7 @@ module.exports = function () { // Requirements //------------------------------------------------------------------------------ -var debug = require("debug")("eslint:text-fixer"); +var debug = require("debug")("eslint:source-code-fixer"); //------------------------------------------------------------------------------ // Helpers @@ -100502,7 +111816,7 @@ SourceCodeFixer.applyFixes = function (sourceText, messages, shouldFix) { } messages.forEach(function (problem) { - if (problem.hasOwnProperty("fix")) { + if (Object.prototype.hasOwnProperty.call(problem, "fix")) { fixes.push(problem); } else { remainingMessages.push(problem); @@ -100567,7 +111881,7 @@ SourceCodeFixer.applyFixes = function (sourceText, messages, shouldFix) { module.exports = SourceCodeFixer; -},{"debug":52}],411:[function(require,module,exports){ +},{"debug":53}],416:[function(require,module,exports){ /** * @fileoverview Abstraction of JavaScript source code. * @author Nicholas C. Zakas @@ -100590,7 +111904,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var TokenStore = require("../token-store"), Traverser = require("./traverser"), - astUtils = require("../ast-utils"), + astUtils = require("../util/ast-utils"), lodash = require("lodash"); //------------------------------------------------------------------------------ @@ -100667,16 +111981,17 @@ var SourceCode = function (_TokenStore) { * @param {string|Object} textOrConfig - The source code text or config object. * @param {string} textOrConfig.text - The source code text. * @param {ASTNode} textOrConfig.ast - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped. - * @param {Object|null} textOrConfig.parserServices - The parser srevices. + * @param {Object|null} textOrConfig.parserServices - The parser services. * @param {ScopeManager|null} textOrConfig.scopeManager - The scope of this source code. * @param {Object|null} textOrConfig.visitorKeys - The visitor keys to traverse AST. - * @param {ASTNode} [ast] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped. + * @param {ASTNode} [astIfNoConfig] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped. * @constructor */ - function SourceCode(textOrConfig, ast) { + function SourceCode(textOrConfig, astIfNoConfig) { _classCallCheck(this, SourceCode); var text = void 0, + ast = void 0, parserServices = void 0, scopeManager = void 0, visitorKeys = void 0; @@ -100684,6 +111999,7 @@ var SourceCode = function (_TokenStore) { // Process overloading. if (typeof textOrConfig === "string") { text = textOrConfig; + ast = astIfNoConfig; } else if ((typeof textOrConfig === "undefined" ? "undefined" : _typeof(textOrConfig)) === "object" && textOrConfig !== null) { text = textOrConfig.text; ast = textOrConfig.ast; @@ -100908,6 +112224,7 @@ var SourceCode = function (_TokenStore) { * @returns {Token|null} The Block comment token containing the JSDoc comment * for the given node or null if not found. * @public + * @deprecated */ }, { @@ -100975,15 +112292,13 @@ var SourceCode = function (_TokenStore) { }, { key: "getNodeByRangeIndex", value: function getNodeByRangeIndex(index) { - var result = null, - resultParent = null; + var result = null; Traverser.traverse(this.ast, { visitorKeys: this.visitorKeys, - enter: function enter(node, parent) { + enter: function enter(node) { if (node.range[0] <= index && index < node.range[1]) { result = node; - resultParent = parent; } else { this.skip(); } @@ -100995,7 +112310,7 @@ var SourceCode = function (_TokenStore) { } }); - return result ? Object.assign({ parent: resultParent }, result) : null; + return result; } /** @@ -101110,7 +112425,149 @@ var SourceCode = function (_TokenStore) { module.exports = SourceCode; -},{"../ast-utils":115,"../token-store":396,"./traverser":412,"lodash":89}],412:[function(require,module,exports){ +},{"../token-store":398,"../util/ast-utils":405,"./traverser":418,"lodash":92}],417:[function(require,module,exports){ +(function (process){ +/** + * @fileoverview Tracks performance of individual rules. + * @author Brandon Mills + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/* istanbul ignore next */ +/** + * Align the string to left + * @param {string} str string to evaluate + * @param {int} len length of the string + * @param {string} ch delimiter character + * @returns {string} modified string + * @private + */ + +function alignLeft(str, len, ch) { + return str + new Array(len - str.length + 1).join(ch || " "); +} + +/* istanbul ignore next */ +/** + * Align the string to right + * @param {string} str string to evaluate + * @param {int} len length of the string + * @param {string} ch delimiter character + * @returns {string} modified string + * @private + */ +function alignRight(str, len, ch) { + return new Array(len - str.length + 1).join(ch || " ") + str; +} + +//------------------------------------------------------------------------------ +// Module definition +//------------------------------------------------------------------------------ + +var enabled = !!process.env.TIMING; + +var HEADERS = ["Rule", "Time (ms)", "Relative"]; +var ALIGN = [alignLeft, alignRight, alignRight]; + +/* istanbul ignore next */ +/** + * display the data + * @param {Object} data Data object to be displayed + * @returns {string} modified string + * @private + */ +function display(data) { + var total = 0; + var rows = Object.keys(data).map(function (key) { + var time = data[key]; + + total += time; + return [key, time]; + }).sort(function (a, b) { + return b[1] - a[1]; + }).slice(0, 10); + + rows.forEach(function (row) { + row.push((row[1] * 100 / total).toFixed(1) + "%"); + row[1] = row[1].toFixed(3); + }); + + rows.unshift(HEADERS); + + var widths = []; + + rows.forEach(function (row) { + var len = row.length; + + for (var i = 0; i < len; i++) { + var n = row[i].length; + + if (!widths[i] || n > widths[i]) { + widths[i] = n; + } + } + }); + + var table = rows.map(function (row) { + return row.map(function (cell, index) { + return ALIGN[index](cell, widths[index]); + }).join(" | "); + }); + + table.splice(1, 0, widths.map(function (width, index) { + var extraAlignment = index !== 0 && index !== widths.length - 1 ? 2 : 1; + + return ALIGN[index](":", width + extraAlignment, "-"); + }).join("|")); + + console.log(table.join("\n")); // eslint-disable-line no-console +} + +/* istanbul ignore next */ +module.exports = function () { + + var data = Object.create(null); + + /** + * Time the run + * @param {*} key key from the data object + * @param {Function} fn function to be called + * @returns {Function} function to be executed + * @private + */ + function time(key, fn) { + if (typeof data[key] === "undefined") { + data[key] = 0; + } + + return function () { + var t = process.hrtime(); + + fn.apply(undefined, arguments); + t = process.hrtime(t); + data[key] += t[0] * 1e3 + t[1] / 1e6; + }; + } + + if (enabled) { + process.on("exit", function () { + display(data); + }); + } + + return { + time: time, + enabled: enabled + }; +}(); + +}).call(this,require('_process')) +},{"_process":103}],418:[function(require,module,exports){ /** * @fileoverview Traverser to traverse AST trees. * @author Nicholas C. Zakas @@ -101345,5 +112802,82 @@ var Traverser = function () { module.exports = Traverser; -},{"debug":52,"eslint-visitor-keys":67}]},{},[126])(126) -}); \ No newline at end of file +},{"debug":53,"eslint-visitor-keys":69}],419:[function(require,module,exports){ +/** + * @author Toru Nagashima + */ +"use strict"; + +module.exports = { + isCombiningCharacter: require("./is-combining-character"), + isEmojiModifier: require("./is-emoji-modifier"), + isRegionalIndicatorSymbol: require("./is-regional-indicator-symbol"), + isSurrogatePair: require("./is-surrogate-pair") +}; + +},{"./is-combining-character":420,"./is-emoji-modifier":421,"./is-regional-indicator-symbol":422,"./is-surrogate-pair":423}],420:[function(require,module,exports){ +// THIS FILE WAS GENERATED BY 'tools/update-unicode-utils.js' +"use strict"; + +var combiningChars = new Set([768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1471, 1473, 1474, 1476, 1477, 1479, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1648, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1759, 1760, 1761, 1762, 1763, 1764, 1767, 1768, 1770, 1771, 1772, 1773, 1809, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2070, 2071, 2072, 2073, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2085, 2086, 2087, 2089, 2090, 2091, 2092, 2093, 2137, 2138, 2139, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2362, 2363, 2364, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2402, 2403, 2433, 2434, 2435, 2492, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2503, 2504, 2507, 2508, 2509, 2519, 2530, 2531, 2561, 2562, 2563, 2620, 2622, 2623, 2624, 2625, 2626, 2631, 2632, 2635, 2636, 2637, 2641, 2672, 2673, 2677, 2689, 2690, 2691, 2748, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2759, 2760, 2761, 2763, 2764, 2765, 2786, 2787, 2810, 2811, 2812, 2813, 2814, 2815, 2817, 2818, 2819, 2876, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2887, 2888, 2891, 2892, 2893, 2902, 2903, 2914, 2915, 2946, 3006, 3007, 3008, 3009, 3010, 3014, 3015, 3016, 3018, 3019, 3020, 3021, 3031, 3072, 3073, 3074, 3075, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3142, 3143, 3144, 3146, 3147, 3148, 3149, 3157, 3158, 3170, 3171, 3201, 3202, 3203, 3260, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3270, 3271, 3272, 3274, 3275, 3276, 3277, 3285, 3286, 3298, 3299, 3328, 3329, 3330, 3331, 3387, 3388, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3398, 3399, 3400, 3402, 3403, 3404, 3405, 3415, 3426, 3427, 3458, 3459, 3530, 3535, 3536, 3537, 3538, 3539, 3540, 3542, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3570, 3571, 3633, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3761, 3764, 3765, 3766, 3767, 3768, 3769, 3771, 3772, 3784, 3785, 3786, 3787, 3788, 3789, 3864, 3865, 3893, 3895, 3897, 3902, 3903, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3974, 3975, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4038, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4182, 4183, 4184, 4185, 4190, 4191, 4192, 4194, 4195, 4196, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4209, 4210, 4211, 4212, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4239, 4250, 4251, 4252, 4253, 4957, 4958, 4959, 5906, 5907, 5908, 5938, 5939, 5940, 5970, 5971, 6002, 6003, 6068, 6069, 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6087, 6088, 6089, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6109, 6155, 6156, 6157, 6277, 6278, 6313, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6679, 6680, 6681, 6682, 6683, 6741, 6742, 6743, 6744, 6745, 6746, 6747, 6748, 6749, 6750, 6752, 6753, 6754, 6755, 6756, 6757, 6758, 6759, 6760, 6761, 6762, 6763, 6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, 6772, 6773, 6774, 6775, 6776, 6777, 6778, 6779, 6780, 6783, 6832, 6833, 6834, 6835, 6836, 6837, 6838, 6839, 6840, 6841, 6842, 6843, 6844, 6845, 6846, 6912, 6913, 6914, 6915, 6916, 6964, 6965, 6966, 6967, 6968, 6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978, 6979, 6980, 7019, 7020, 7021, 7022, 7023, 7024, 7025, 7026, 7027, 7040, 7041, 7042, 7073, 7074, 7075, 7076, 7077, 7078, 7079, 7080, 7081, 7082, 7083, 7084, 7085, 7142, 7143, 7144, 7145, 7146, 7147, 7148, 7149, 7150, 7151, 7152, 7153, 7154, 7155, 7204, 7205, 7206, 7207, 7208, 7209, 7210, 7211, 7212, 7213, 7214, 7215, 7216, 7217, 7218, 7219, 7220, 7221, 7222, 7223, 7376, 7377, 7378, 7380, 7381, 7382, 7383, 7384, 7385, 7386, 7387, 7388, 7389, 7390, 7391, 7392, 7393, 7394, 7395, 7396, 7397, 7398, 7399, 7400, 7405, 7410, 7411, 7412, 7415, 7416, 7417, 7616, 7617, 7618, 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626, 7627, 7628, 7629, 7630, 7631, 7632, 7633, 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642, 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650, 7651, 7652, 7653, 7654, 7655, 7656, 7657, 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666, 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7675, 7676, 7677, 7678, 7679, 8400, 8401, 8402, 8403, 8404, 8405, 8406, 8407, 8408, 8409, 8410, 8411, 8412, 8413, 8414, 8415, 8416, 8417, 8418, 8419, 8420, 8421, 8422, 8423, 8424, 8425, 8426, 8427, 8428, 8429, 8430, 8431, 8432, 11503, 11504, 11505, 11647, 11744, 11745, 11746, 11747, 11748, 11749, 11750, 11751, 11752, 11753, 11754, 11755, 11756, 11757, 11758, 11759, 11760, 11761, 11762, 11763, 11764, 11765, 11766, 11767, 11768, 11769, 11770, 11771, 11772, 11773, 11774, 11775, 12330, 12331, 12332, 12333, 12334, 12335, 12441, 12442, 42607, 42608, 42609, 42610, 42612, 42613, 42614, 42615, 42616, 42617, 42618, 42619, 42620, 42621, 42654, 42655, 42736, 42737, 43010, 43014, 43019, 43043, 43044, 43045, 43046, 43047, 43136, 43137, 43188, 43189, 43190, 43191, 43192, 43193, 43194, 43195, 43196, 43197, 43198, 43199, 43200, 43201, 43202, 43203, 43204, 43205, 43232, 43233, 43234, 43235, 43236, 43237, 43238, 43239, 43240, 43241, 43242, 43243, 43244, 43245, 43246, 43247, 43248, 43249, 43302, 43303, 43304, 43305, 43306, 43307, 43308, 43309, 43335, 43336, 43337, 43338, 43339, 43340, 43341, 43342, 43343, 43344, 43345, 43346, 43347, 43392, 43393, 43394, 43395, 43443, 43444, 43445, 43446, 43447, 43448, 43449, 43450, 43451, 43452, 43453, 43454, 43455, 43456, 43493, 43561, 43562, 43563, 43564, 43565, 43566, 43567, 43568, 43569, 43570, 43571, 43572, 43573, 43574, 43587, 43596, 43597, 43643, 43644, 43645, 43696, 43698, 43699, 43700, 43703, 43704, 43710, 43711, 43713, 43755, 43756, 43757, 43758, 43759, 43765, 43766, 44003, 44004, 44005, 44006, 44007, 44008, 44009, 44010, 44012, 44013, 64286, 65024, 65025, 65026, 65027, 65028, 65029, 65030, 65031, 65032, 65033, 65034, 65035, 65036, 65037, 65038, 65039, 65056, 65057, 65058, 65059, 65060, 65061, 65062, 65063, 65064, 65065, 65066, 65067, 65068, 65069, 65070, 65071, 66045, 66272, 66422, 66423, 66424, 66425, 66426, 68097, 68098, 68099, 68101, 68102, 68108, 68109, 68110, 68111, 68152, 68153, 68154, 68159, 68325, 68326, 69632, 69633, 69634, 69688, 69689, 69690, 69691, 69692, 69693, 69694, 69695, 69696, 69697, 69698, 69699, 69700, 69701, 69702, 69759, 69760, 69761, 69762, 69808, 69809, 69810, 69811, 69812, 69813, 69814, 69815, 69816, 69817, 69818, 69888, 69889, 69890, 69927, 69928, 69929, 69930, 69931, 69932, 69933, 69934, 69935, 69936, 69937, 69938, 69939, 69940, 70003, 70016, 70017, 70018, 70067, 70068, 70069, 70070, 70071, 70072, 70073, 70074, 70075, 70076, 70077, 70078, 70079, 70080, 70090, 70091, 70092, 70188, 70189, 70190, 70191, 70192, 70193, 70194, 70195, 70196, 70197, 70198, 70199, 70206, 70367, 70368, 70369, 70370, 70371, 70372, 70373, 70374, 70375, 70376, 70377, 70378, 70400, 70401, 70402, 70403, 70460, 70462, 70463, 70464, 70465, 70466, 70467, 70468, 70471, 70472, 70475, 70476, 70477, 70487, 70498, 70499, 70502, 70503, 70504, 70505, 70506, 70507, 70508, 70512, 70513, 70514, 70515, 70516, 70709, 70710, 70711, 70712, 70713, 70714, 70715, 70716, 70717, 70718, 70719, 70720, 70721, 70722, 70723, 70724, 70725, 70726, 70832, 70833, 70834, 70835, 70836, 70837, 70838, 70839, 70840, 70841, 70842, 70843, 70844, 70845, 70846, 70847, 70848, 70849, 70850, 70851, 71087, 71088, 71089, 71090, 71091, 71092, 71093, 71096, 71097, 71098, 71099, 71100, 71101, 71102, 71103, 71104, 71132, 71133, 71216, 71217, 71218, 71219, 71220, 71221, 71222, 71223, 71224, 71225, 71226, 71227, 71228, 71229, 71230, 71231, 71232, 71339, 71340, 71341, 71342, 71343, 71344, 71345, 71346, 71347, 71348, 71349, 71350, 71351, 71453, 71454, 71455, 71456, 71457, 71458, 71459, 71460, 71461, 71462, 71463, 71464, 71465, 71466, 71467, 72193, 72194, 72195, 72196, 72197, 72198, 72199, 72200, 72201, 72202, 72243, 72244, 72245, 72246, 72247, 72248, 72249, 72251, 72252, 72253, 72254, 72263, 72273, 72274, 72275, 72276, 72277, 72278, 72279, 72280, 72281, 72282, 72283, 72330, 72331, 72332, 72333, 72334, 72335, 72336, 72337, 72338, 72339, 72340, 72341, 72342, 72343, 72344, 72345, 72751, 72752, 72753, 72754, 72755, 72756, 72757, 72758, 72760, 72761, 72762, 72763, 72764, 72765, 72766, 72767, 72850, 72851, 72852, 72853, 72854, 72855, 72856, 72857, 72858, 72859, 72860, 72861, 72862, 72863, 72864, 72865, 72866, 72867, 72868, 72869, 72870, 72871, 72873, 72874, 72875, 72876, 72877, 72878, 72879, 72880, 72881, 72882, 72883, 72884, 72885, 72886, 73009, 73010, 73011, 73012, 73013, 73014, 73018, 73020, 73021, 73023, 73024, 73025, 73026, 73027, 73028, 73029, 73031, 92912, 92913, 92914, 92915, 92916, 92976, 92977, 92978, 92979, 92980, 92981, 92982, 94033, 94034, 94035, 94036, 94037, 94038, 94039, 94040, 94041, 94042, 94043, 94044, 94045, 94046, 94047, 94048, 94049, 94050, 94051, 94052, 94053, 94054, 94055, 94056, 94057, 94058, 94059, 94060, 94061, 94062, 94063, 94064, 94065, 94066, 94067, 94068, 94069, 94070, 94071, 94072, 94073, 94074, 94075, 94076, 94077, 94078, 94095, 94096, 94097, 94098, 113821, 113822, 119141, 119142, 119143, 119144, 119145, 119149, 119150, 119151, 119152, 119153, 119154, 119163, 119164, 119165, 119166, 119167, 119168, 119169, 119170, 119173, 119174, 119175, 119176, 119177, 119178, 119179, 119210, 119211, 119212, 119213, 119362, 119363, 119364, 121344, 121345, 121346, 121347, 121348, 121349, 121350, 121351, 121352, 121353, 121354, 121355, 121356, 121357, 121358, 121359, 121360, 121361, 121362, 121363, 121364, 121365, 121366, 121367, 121368, 121369, 121370, 121371, 121372, 121373, 121374, 121375, 121376, 121377, 121378, 121379, 121380, 121381, 121382, 121383, 121384, 121385, 121386, 121387, 121388, 121389, 121390, 121391, 121392, 121393, 121394, 121395, 121396, 121397, 121398, 121403, 121404, 121405, 121406, 121407, 121408, 121409, 121410, 121411, 121412, 121413, 121414, 121415, 121416, 121417, 121418, 121419, 121420, 121421, 121422, 121423, 121424, 121425, 121426, 121427, 121428, 121429, 121430, 121431, 121432, 121433, 121434, 121435, 121436, 121437, 121438, 121439, 121440, 121441, 121442, 121443, 121444, 121445, 121446, 121447, 121448, 121449, 121450, 121451, 121452, 121461, 121476, 121499, 121500, 121501, 121502, 121503, 121505, 121506, 121507, 121508, 121509, 121510, 121511, 121512, 121513, 121514, 121515, 121516, 121517, 121518, 121519, 122880, 122881, 122882, 122883, 122884, 122885, 122886, 122888, 122889, 122890, 122891, 122892, 122893, 122894, 122895, 122896, 122897, 122898, 122899, 122900, 122901, 122902, 122903, 122904, 122907, 122908, 122909, 122910, 122911, 122912, 122913, 122915, 122916, 122918, 122919, 122920, 122921, 122922, 125136, 125137, 125138, 125139, 125140, 125141, 125142, 125252, 125253, 125254, 125255, 125256, 125257, 125258, 917760, 917761, 917762, 917763, 917764, 917765, 917766, 917767, 917768, 917769, 917770, 917771, 917772, 917773, 917774, 917775, 917776, 917777, 917778, 917779, 917780, 917781, 917782, 917783, 917784, 917785, 917786, 917787, 917788, 917789, 917790, 917791, 917792, 917793, 917794, 917795, 917796, 917797, 917798, 917799, 917800, 917801, 917802, 917803, 917804, 917805, 917806, 917807, 917808, 917809, 917810, 917811, 917812, 917813, 917814, 917815, 917816, 917817, 917818, 917819, 917820, 917821, 917822, 917823, 917824, 917825, 917826, 917827, 917828, 917829, 917830, 917831, 917832, 917833, 917834, 917835, 917836, 917837, 917838, 917839, 917840, 917841, 917842, 917843, 917844, 917845, 917846, 917847, 917848, 917849, 917850, 917851, 917852, 917853, 917854, 917855, 917856, 917857, 917858, 917859, 917860, 917861, 917862, 917863, 917864, 917865, 917866, 917867, 917868, 917869, 917870, 917871, 917872, 917873, 917874, 917875, 917876, 917877, 917878, 917879, 917880, 917881, 917882, 917883, 917884, 917885, 917886, 917887, 917888, 917889, 917890, 917891, 917892, 917893, 917894, 917895, 917896, 917897, 917898, 917899, 917900, 917901, 917902, 917903, 917904, 917905, 917906, 917907, 917908, 917909, 917910, 917911, 917912, 917913, 917914, 917915, 917916, 917917, 917918, 917919, 917920, 917921, 917922, 917923, 917924, 917925, 917926, 917927, 917928, 917929, 917930, 917931, 917932, 917933, 917934, 917935, 917936, 917937, 917938, 917939, 917940, 917941, 917942, 917943, 917944, 917945, 917946, 917947, 917948, 917949, 917950, 917951, 917952, 917953, 917954, 917955, 917956, 917957, 917958, 917959, 917960, 917961, 917962, 917963, 917964, 917965, 917966, 917967, 917968, 917969, 917970, 917971, 917972, 917973, 917974, 917975, 917976, 917977, 917978, 917979, 917980, 917981, 917982, 917983, 917984, 917985, 917986, 917987, 917988, 917989, 917990, 917991, 917992, 917993, 917994, 917995, 917996, 917997, 917998, 917999]); + +/** + * Check whether a given character is a combining mark or not. + * @param {number} c The character code to check. + * @returns {boolean} `true` if the character belongs to the category, one of `Mc`, `Me`, and `Mn`. + */ +module.exports = function isCombiningCharacter(c) { + return combiningChars.has(c); +}; + +},{}],421:[function(require,module,exports){ +/** + * @author Toru Nagashima + */ +"use strict"; + +/** + * Check whether a given character is an emoji modifier. + * @param {number} code The character code to check. + * @returns {boolean} `true` if the character is an emoji modifier. + */ + +module.exports = function isEmojiModifier(code) { + return code >= 0x1F3FB && code <= 0x1F3FF; +}; + +},{}],422:[function(require,module,exports){ +/** + * @author Toru Nagashima + */ +"use strict"; + +/** + * Check whether a given character is a regional indicator symbol. + * @param {number} code The character code to check. + * @returns {boolean} `true` if the character is a regional indicator symbol. + */ + +module.exports = function isRegionalIndicatorSymbol(code) { + return code >= 0x1F1E6 && code <= 0x1F1FF; +}; + +},{}],423:[function(require,module,exports){ +/** + * @author Toru Nagashima + */ +"use strict"; + +/** + * Check whether given two characters are a surrogate pair. + * @param {number} lead The code of the lead character. + * @param {number} tail The code of the tail character. + * @returns {boolean} `true` if the character pair is a surrogate pair. + */ + +module.exports = function isSurrogatePair(lead, tail) { + return lead >= 0xD800 && lead < 0xDC00 && tail >= 0xDC00 && tail < 0xE000; +}; + +},{}]},{},[122])(122) +});