Comparing version 4.0.0 to 4.1.0
@@ -0,1 +1,8 @@ | ||
v4.1.0 - October 24, 2018 | ||
* 8eadb88 Upgrade: acorn 6, acorn-jsx 5, and istanbul (#391) (Toru Nagashima) | ||
* 0f2edb8 Upgrade: eslint-release@1.0.0 (#392) (Teddy Katz) | ||
* 560b6f7 Update: VisitorKeys depend on eslint-visitor-keys (#389) (othree) | ||
* 6bf2ebf Docs: Fix some typos in the README (#386) (Hugo Locurcio) | ||
v4.0.0 - June 21, 2018 | ||
@@ -2,0 +9,0 @@ |
553
espree.js
@@ -61,267 +61,34 @@ /** | ||
var astNodeTypes = require("./lib/ast-node-types"), | ||
commentAttachment = require("./lib/comment-attachment"), | ||
TokenTranslator = require("./lib/token-translator"), | ||
acornJSX = require("acorn-jsx/inject"), | ||
rawAcorn = require("acorn"); | ||
const acorn = require("acorn"); | ||
const jsx = require("acorn-jsx"); | ||
const astNodeTypes = require("./lib/ast-node-types"); | ||
const espree = require("./lib/espree"); | ||
// To initialize lazily. | ||
const parsers = { | ||
_regular: null, | ||
_jsx: null, | ||
var acorn = acornJSX(rawAcorn); | ||
var DEFAULT_ECMA_VERSION = 5; | ||
var lookahead, | ||
extra, | ||
lastToken; | ||
/** | ||
* Resets the extra object to its default. | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function resetExtra() { | ||
extra = { | ||
tokens: null, | ||
range: false, | ||
loc: false, | ||
comment: false, | ||
comments: [], | ||
tolerant: false, | ||
errors: [], | ||
strict: false, | ||
ecmaFeatures: {}, | ||
ecmaVersion: DEFAULT_ECMA_VERSION, | ||
isModule: false | ||
}; | ||
} | ||
var tt = acorn.tokTypes, | ||
getLineInfo = acorn.getLineInfo; | ||
// custom type for JSX attribute values | ||
tt.jsxAttrValueToken = {}; | ||
/** | ||
* Normalize ECMAScript version from the initial config | ||
* @param {number} ecmaVersion ECMAScript version from the initial config | ||
* @returns {number} normalized ECMAScript version | ||
*/ | ||
function normalizeEcmaVersion(ecmaVersion) { | ||
if (typeof ecmaVersion === "number") { | ||
var version = ecmaVersion; | ||
// Calculate ECMAScript edition number from official year version starting with | ||
// ES2015, which corresponds with ES6 (or a difference of 2009). | ||
if (version >= 2015) { | ||
version -= 2009; | ||
get regular() { | ||
if (this._regular === null) { | ||
this._regular = acorn.Parser.extend(espree()); | ||
} | ||
return this._regular; | ||
}, | ||
switch (version) { | ||
case 3: | ||
case 5: | ||
case 6: | ||
case 7: | ||
case 8: | ||
case 9: | ||
case 10: | ||
return version; | ||
default: | ||
throw new Error("Invalid ecmaVersion."); | ||
get jsx() { | ||
if (this._jsx === null) { | ||
this._jsx = acorn.Parser.extend(jsx(), espree()); | ||
} | ||
} else { | ||
return DEFAULT_ECMA_VERSION; | ||
} | ||
} | ||
return this._jsx; | ||
}, | ||
/** | ||
* Determines if a node is valid given the set of ecmaFeatures. | ||
* @param {ASTNode} node The node to check. | ||
* @returns {boolean} True if the node is allowed, false if not. | ||
* @private | ||
*/ | ||
function isValidNode(node) { | ||
switch (node.type) { | ||
case "ImportDeclaration": | ||
case "ExportNamedDeclaration": | ||
case "ExportDefaultDeclaration": | ||
case "ExportAllDeclaration": | ||
return extra.isModule; | ||
default: | ||
return true; | ||
get(options) { | ||
const useJsx = Boolean( | ||
options && | ||
options.ecmaFeatures && | ||
options.ecmaFeatures.jsx | ||
); | ||
return useJsx ? this.jsx : this.regular; | ||
} | ||
} | ||
/** | ||
* Performs last-minute Esprima-specific compatibility checks and fixes. | ||
* @param {ASTNode} result The node to check. | ||
* @returns {ASTNode} The finished node. | ||
* @private | ||
* @this acorn.Parser | ||
*/ | ||
function esprimaFinishNode(result) { | ||
// ensure that parsed node was allowed through ecmaFeatures | ||
if (!isValidNode(result)) { | ||
this.unexpected(result.start); | ||
} | ||
// Acorn doesn't count the opening and closing backticks as part of templates | ||
// so we have to adjust ranges/locations appropriately. | ||
if (result.type === "TemplateElement") { | ||
// additional adjustment needed if ${ is the last token | ||
var terminalDollarBraceL = this.input.slice(result.end, result.end + 2) === "${"; | ||
if (result.range) { | ||
result.range[0]--; | ||
result.range[1] += (terminalDollarBraceL ? 2 : 1); | ||
} | ||
if (result.loc) { | ||
result.loc.start.column--; | ||
result.loc.end.column += (terminalDollarBraceL ? 2 : 1); | ||
} | ||
} | ||
if (extra.attachComment) { | ||
commentAttachment.processComment(result); | ||
} | ||
if (result.type.indexOf("Function") > -1 && !result.generator) { | ||
result.generator = false; | ||
} | ||
return result; | ||
} | ||
/** | ||
* Determines if a token is valid given the set of ecmaFeatures. | ||
* @param {acorn.Parser} parser The parser to check. | ||
* @returns {boolean} True if the token is allowed, false if not. | ||
* @private | ||
*/ | ||
function isValidToken(parser) { | ||
var ecma = extra.ecmaFeatures; | ||
var type = parser.type; | ||
switch (type) { | ||
case tt.jsxName: | ||
case tt.jsxText: | ||
case tt.jsxTagStart: | ||
case tt.jsxTagEnd: | ||
return ecma.jsx; | ||
// https://github.com/ternjs/acorn/issues/363 | ||
case tt.regexp: | ||
if (extra.ecmaVersion < 6 && parser.value.flags && parser.value.flags.indexOf("y") > -1) { | ||
return false; | ||
} | ||
return true; | ||
default: | ||
return true; | ||
} | ||
} | ||
/** | ||
* Injects esprimaFinishNode into the finishNode process. | ||
* @param {Function} finishNode Original finishNode function. | ||
* @returns {ASTNode} The finished node. | ||
* @private | ||
*/ | ||
function wrapFinishNode(finishNode) { | ||
return /** @this acorn.Parser */ function(node, type, pos, loc) { | ||
var result = finishNode.call(this, node, type, pos, loc); | ||
return esprimaFinishNode.call(this, result); | ||
}; | ||
} | ||
acorn.plugins.espree = function(instance) { | ||
instance.extend("finishNode", wrapFinishNode); | ||
instance.extend("finishNodeAt", wrapFinishNode); | ||
instance.extend("next", function(next) { | ||
return /** @this acorn.Parser */ function() { | ||
if (!isValidToken(this)) { | ||
this.unexpected(); | ||
} | ||
return next.call(this); | ||
}; | ||
}); | ||
instance.extend("parseTopLevel", function(parseTopLevel) { | ||
return /** @this acorn.Parser */ function(node) { | ||
if (extra.ecmaFeatures.impliedStrict && this.options.ecmaVersion >= 5) { | ||
this.strict = true; | ||
} | ||
return parseTopLevel.call(this, node); | ||
}; | ||
}); | ||
/** | ||
* Overwrites the default raise method to throw Esprima-style errors. | ||
* @param {int} pos The position of the error. | ||
* @param {string} message The error message. | ||
* @throws {SyntaxError} A syntax error. | ||
* @returns {void} | ||
*/ | ||
instance.raise = instance.raiseRecoverable = function(pos, message) { | ||
var loc = getLineInfo(this.input, pos); | ||
var err = new SyntaxError(message); | ||
err.index = pos; | ||
err.lineNumber = loc.line; | ||
err.column = loc.column + 1; // acorn uses 0-based columns | ||
throw err; | ||
}; | ||
/** | ||
* Overwrites the default unexpected method to throw Esprima-style errors. | ||
* @param {int} pos The position of the error. | ||
* @throws {SyntaxError} A syntax error. | ||
* @returns {void} | ||
*/ | ||
instance.unexpected = function(pos) { | ||
var message = "Unexpected token"; | ||
if (pos !== null && pos !== undefined) { | ||
this.pos = pos; | ||
if (this.options.locations) { | ||
while (this.pos < this.lineStart) { | ||
this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1; | ||
--this.curLine; | ||
} | ||
} | ||
this.nextToken(); | ||
} | ||
if (this.end > this.start) { | ||
message += " " + this.input.slice(this.start, this.end); | ||
} | ||
this.raise(this.start, message); | ||
}; | ||
/* | ||
* Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX | ||
* uses regular tt.string without any distinction between this and regular JS | ||
* strings. As such, we intercept an attempt to read a JSX string and set a flag | ||
* on extra so that when tokens are converted, the next token will be switched | ||
* to JSXText via onToken. | ||
*/ | ||
instance.extend("jsx_readString", function(jsxReadString) { | ||
return /** @this acorn.Parser */ function(quote) { | ||
var result = jsxReadString.call(this, quote); | ||
if (this.type === tt.string) { | ||
extra.jsxAttrValueToken = true; | ||
} | ||
return result; | ||
}; | ||
}); | ||
}; | ||
@@ -342,75 +109,10 @@ | ||
function tokenize(code, options) { | ||
var toString, | ||
tokens, | ||
impliedStrict, | ||
translator = new TokenTranslator(tt, code); | ||
const Parser = parsers.get(options); | ||
toString = String; | ||
if (typeof code !== "string" && !(code instanceof String)) { | ||
code = toString(code); | ||
// Ensure to collect tokens. | ||
if (!options || options.tokens !== true) { | ||
options = Object.assign({}, options, { tokens: true }); | ||
} | ||
lookahead = null; | ||
// Options matching. | ||
options = Object.assign({}, options); | ||
var acornOptions = { | ||
ecmaVersion: DEFAULT_ECMA_VERSION, | ||
plugins: { | ||
espree: true | ||
} | ||
}; | ||
resetExtra(); | ||
// Of course we collect tokens here. | ||
options.tokens = true; | ||
extra.tokens = []; | ||
extra.range = (typeof options.range === "boolean") && options.range; | ||
acornOptions.ranges = extra.range; | ||
extra.loc = (typeof options.loc === "boolean") && options.loc; | ||
acornOptions.locations = extra.loc; | ||
extra.comment = typeof options.comment === "boolean" && options.comment; | ||
if (extra.comment) { | ||
acornOptions.onComment = function() { | ||
var comment = convertAcornCommentToEsprimaComment.apply(this, arguments); | ||
extra.comments.push(comment); | ||
}; | ||
} | ||
extra.tolerant = typeof options.tolerant === "boolean" && options.tolerant; | ||
acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); | ||
// apply parsing flags | ||
if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") { | ||
extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures); | ||
impliedStrict = extra.ecmaFeatures.impliedStrict; | ||
extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict; | ||
} | ||
try { | ||
var tokenizer = acorn.tokenizer(code, acornOptions); | ||
while ((lookahead = tokenizer.getToken()).type !== tt.eof) { | ||
translator.onToken(lookahead, extra); | ||
} | ||
// filterTokenLocation(); | ||
tokens = extra.tokens; | ||
if (extra.comment) { | ||
tokens.comments = extra.comments; | ||
} | ||
if (extra.tolerant) { | ||
tokens.errors = extra.errors; | ||
} | ||
} catch (e) { | ||
throw e; | ||
} | ||
return tokens; | ||
return new Parser(options, code).tokenize(); | ||
} | ||
@@ -422,38 +124,3 @@ | ||
/** | ||
* Converts an Acorn comment to a Esprima comment. | ||
* @param {boolean} block True if it's a block comment, false if not. | ||
* @param {string} text The text of the comment. | ||
* @param {int} start The index at which the comment starts. | ||
* @param {int} end The index at which the comment ends. | ||
* @param {Location} startLoc The location at which the comment starts. | ||
* @param {Location} endLoc The location at which the comment ends. | ||
* @returns {Object} The comment object. | ||
* @private | ||
*/ | ||
function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc) { | ||
var comment = { | ||
type: block ? "Block" : "Line", | ||
value: text | ||
}; | ||
if (typeof start === "number") { | ||
comment.start = start; | ||
comment.end = end; | ||
comment.range = [start, end]; | ||
} | ||
if (typeof startLoc === "object") { | ||
comment.loc = { | ||
start: startLoc, | ||
end: endLoc | ||
}; | ||
} | ||
return comment; | ||
} | ||
/** | ||
* Parses the given code. | ||
@@ -464,142 +131,6 @@ * @param {string} code The code to tokenize. | ||
* @throws {SyntaxError} If the input code is invalid. | ||
* @private | ||
*/ | ||
function parse(code, options) { | ||
var program, | ||
toString = String, | ||
translator, | ||
impliedStrict, | ||
acornOptions = { | ||
ecmaVersion: DEFAULT_ECMA_VERSION, | ||
plugins: { | ||
espree: true | ||
} | ||
}; | ||
lastToken = null; | ||
if (typeof code !== "string" && !(code instanceof String)) { | ||
code = toString(code); | ||
} | ||
resetExtra(); | ||
commentAttachment.reset(); | ||
if (typeof options !== "undefined") { | ||
extra.range = (typeof options.range === "boolean") && options.range; | ||
extra.loc = (typeof options.loc === "boolean") && options.loc; | ||
extra.attachComment = (typeof options.attachComment === "boolean") && options.attachComment; | ||
if (extra.loc && options.source !== null && options.source !== undefined) { | ||
extra.source = toString(options.source); | ||
} | ||
if (typeof options.tokens === "boolean" && options.tokens) { | ||
extra.tokens = []; | ||
translator = new TokenTranslator(tt, code); | ||
} | ||
if (typeof options.comment === "boolean" && options.comment) { | ||
extra.comment = true; | ||
extra.comments = []; | ||
} | ||
if (typeof options.tolerant === "boolean" && options.tolerant) { | ||
extra.errors = []; | ||
} | ||
if (extra.attachComment) { | ||
extra.range = true; | ||
extra.comments = []; | ||
commentAttachment.reset(); | ||
} | ||
acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion); | ||
if (options.sourceType === "module") { | ||
extra.isModule = true; | ||
// modules must be in 6 at least | ||
if (acornOptions.ecmaVersion < 6) { | ||
acornOptions.ecmaVersion = 6; | ||
extra.ecmaVersion = 6; | ||
} | ||
acornOptions.sourceType = "module"; | ||
} | ||
// apply parsing flags after sourceType to allow overriding | ||
if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") { | ||
extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures); | ||
impliedStrict = extra.ecmaFeatures.impliedStrict; | ||
extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict; | ||
if (options.ecmaFeatures.globalReturn) { | ||
acornOptions.allowReturnOutsideFunction = true; | ||
} | ||
} | ||
acornOptions.onToken = function(token) { | ||
if (extra.tokens) { | ||
translator.onToken(token, extra); | ||
} | ||
if (token.type !== tt.eof) { | ||
lastToken = token; | ||
} | ||
}; | ||
if (extra.attachComment || extra.comment) { | ||
acornOptions.onComment = function() { | ||
var comment = convertAcornCommentToEsprimaComment.apply(this, arguments); | ||
extra.comments.push(comment); | ||
if (extra.attachComment) { | ||
commentAttachment.addComment(comment); | ||
} | ||
}; | ||
} | ||
if (extra.range) { | ||
acornOptions.ranges = true; | ||
} | ||
if (extra.loc) { | ||
acornOptions.locations = true; | ||
} | ||
if (extra.ecmaFeatures.jsx) { | ||
// Should process jsx plugin before espree plugin. | ||
acornOptions.plugins = { | ||
jsx: true, | ||
espree: true | ||
}; | ||
} | ||
} | ||
program = acorn.parse(code, acornOptions); | ||
program.sourceType = extra.isModule ? "module" : "script"; | ||
if (extra.comment || extra.attachComment) { | ||
program.comments = extra.comments; | ||
} | ||
if (extra.tokens) { | ||
program.tokens = extra.tokens; | ||
} | ||
/* | ||
* Adjust opening and closing position of program to match Esprima. | ||
* Acorn always starts programs at range 0 whereas Esprima starts at the | ||
* first AST node's start (the only real difference is when there's leading | ||
* whitespace or leading comments). Acorn also counts trailing whitespace | ||
* as part of the program whereas Esprima only counts up to the last token. | ||
*/ | ||
if (program.range) { | ||
program.range[0] = program.body.length ? program.body[0].range[0] : program.range[0]; | ||
program.range[1] = lastToken ? lastToken.range[1] : program.range[1]; | ||
} | ||
if (program.loc) { | ||
program.loc.start = program.body.length ? program.body[0].loc.start : program.loc.start; | ||
program.loc.end = lastToken ? lastToken.loc.end : program.loc.end; | ||
} | ||
return program; | ||
const Parser = parsers.get(options); | ||
return new Parser(options, code).parse(); | ||
} | ||
@@ -641,21 +172,3 @@ | ||
exports.VisitorKeys = (function() { | ||
var visitorKeys = require("./lib/visitor-keys"); | ||
var name, | ||
keys = {}; | ||
if (typeof Object.create === "function") { | ||
keys = Object.create(null); | ||
} | ||
for (name in visitorKeys) { | ||
if (visitorKeys.hasOwnProperty(name)) { | ||
keys[name] = visitorKeys[name]; | ||
} | ||
} | ||
if (typeof Object.freeze === "function") { | ||
Object.freeze(keys); | ||
} | ||
return keys; | ||
return require("eslint-visitor-keys").KEYS; | ||
}()); |
@@ -7,3 +7,3 @@ { | ||
"main": "espree.js", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"files": [ | ||
@@ -22,4 +22,5 @@ "lib", | ||
"dependencies": { | ||
"acorn": "^5.6.0", | ||
"acorn-jsx": "^4.1.1" | ||
"acorn": "^6.0.2", | ||
"acorn-jsx": "^5.0.0", | ||
"eslint-visitor-keys": "^1.0.0" | ||
}, | ||
@@ -31,9 +32,9 @@ "devDependencies": { | ||
"eslint-config-eslint": "^3.0.0", | ||
"eslint-release": "^0.11.1", | ||
"eslint-release": "^1.0.0", | ||
"esprima": "latest", | ||
"esprima-fb": "^8001.2001.0-dev-harmony-fb", | ||
"istanbul": "~0.2.6", | ||
"json-diff": "~0.3.1", | ||
"leche": "^1.0.1", | ||
"mocha": "^2.0.1", | ||
"nyc": "^13.0.1", | ||
"regenerate": "~0.5.4", | ||
@@ -56,10 +57,9 @@ "shelljs": "^0.3.0", | ||
"lint": "node Makefile.js lint", | ||
"release": "eslint-release", | ||
"ci-release": "eslint-ci-release", | ||
"gh-release": "eslint-gh-release", | ||
"alpharelease": "eslint-prerelease alpha", | ||
"betarelease": "eslint-prerelease beta", | ||
"rcrelease": "eslint-prerelease rc", | ||
"browserify": "node Makefile.js browserify" | ||
"browserify": "node Makefile.js browserify", | ||
"generate-release": "eslint-generate-release", | ||
"generate-alpharelease": "eslint-generate-prerelease alpha", | ||
"generate-betarelease": "eslint-generate-prerelease beta", | ||
"generate-rcrelease": "eslint-generate-prerelease rc", | ||
"publish-release": "eslint-publish-release" | ||
} | ||
} |
@@ -153,4 +153,4 @@ [![npm version](https://img.shields.io/npm/v/espree.svg)](https://www.npmjs.com/package/espree) | ||
* RegExp named capture groups | ||
* RegExp lookhehind assersions | ||
* RegExp unicode property escapes | ||
* RegExp lookbehind assertions | ||
* RegExp Unicode property escapes | ||
@@ -157,0 +157,0 @@ Espree supports all of them. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
64988
3
889
+ Addedeslint-visitor-keys@^1.0.0
+ Addedacorn@6.4.2(transitive)
+ Addedacorn-jsx@5.3.2(transitive)
+ Addedeslint-visitor-keys@1.3.0(transitive)
- Removedacorn@5.7.4(transitive)
- Removedacorn-jsx@4.1.1(transitive)
Updatedacorn@^6.0.2
Updatedacorn-jsx@^5.0.0