acorn
Advanced tools
Comparing version 2.4.0 to 2.5.0
@@ -5,2 +5,3 @@ var fs = require("fs"), path = require("path") | ||
var browserify = require("browserify") | ||
var babel = require('babel-core') | ||
var babelify = require("babelify").configure({loose: "all"}) | ||
@@ -69,1 +70,15 @@ | ||
.pipe(fs.createWriteStream("dist/walk.js")) | ||
babel.transformFile("./src/bin/acorn.js", function (err, result) { | ||
if (err) return console.log("Error: " + err.message) | ||
fs.writeFile("bin/acorn", result.code, function (err) { | ||
if (err) return console.log("Error: " + err.message) | ||
// Make bin/acorn executable | ||
if (process.platform === 'win32') | ||
return | ||
var stat = fs.statSync("bin/acorn") | ||
var newPerm = stat.mode | parseInt('111', 8) | ||
fs.chmodSync("bin/acorn", newPerm) | ||
}) | ||
}) |
@@ -306,3 +306,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.acorn || (g.acorn = {})).loose = f()}})(function(){var define,module,exports;return (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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||
elem.value = { | ||
raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), | ||
raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, '\n'), | ||
cooked: this.tok.value | ||
@@ -328,3 +328,3 @@ }; | ||
curElt = this.startNode(); | ||
curElt.value = { cooked: "", raw: "" }; | ||
curElt.value = { cooked: '', raw: '' }; | ||
curElt.tail = true; | ||
@@ -657,12 +657,22 @@ } | ||
LooseParser.prototype.dummyNode = function dummyNode(type) { | ||
var dummy = this.startNode(); | ||
dummy.type = type; | ||
dummy.end = dummy.start; | ||
if (this.options.locations) dummy.loc.end = dummy.loc.start; | ||
if (this.options.ranges) dummy.range[1] = dummy.start; | ||
this.last = { type: _.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc }; | ||
return dummy; | ||
}; | ||
LooseParser.prototype.dummyIdent = function dummyIdent() { | ||
var dummy = this.startNode(); | ||
var dummy = this.dummyNode("Identifier"); | ||
dummy.name = "✖"; | ||
return this.finishNode(dummy, "Identifier"); | ||
return dummy; | ||
}; | ||
LooseParser.prototype.dummyString = function dummyString() { | ||
var dummy = this.startNode(); | ||
var dummy = this.dummyNode("Literal"); | ||
dummy.value = dummy.raw = "✖"; | ||
return this.finishNode(dummy, "Literal"); | ||
return dummy; | ||
}; | ||
@@ -877,3 +887,2 @@ | ||
this.expect(_.tokTypes.parenR); | ||
clause.guard = null; | ||
clause.body = this.parseBlock(); | ||
@@ -1102,3 +1111,3 @@ node.handler = this.finishNode(clause, "CatchClause"); | ||
node.source = this.parseExprAtom(); | ||
node.kind = ""; | ||
node.kind = ''; | ||
} else { | ||
@@ -1113,3 +1122,3 @@ var elt = undefined; | ||
node.specifiers = this.parseImportSpecifierList(); | ||
node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString(); | ||
node.source = this.eatContextual("from") && this.tok.type == _.tokTypes.string ? this.parseExprAtom() : this.dummyString(); | ||
if (elt) node.specifiers.unshift(elt); | ||
@@ -1116,0 +1125,0 @@ } |
@@ -84,3 +84,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.acorn || (g.acorn = {})).walk = f()}})(function(){var define,module,exports;return (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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||
this.node = node;this.state = state; | ||
}; | ||
} | ||
@@ -90,2 +90,3 @@ // Find a node with a given start, end, and type (all are optional, | ||
// undefined when it doesn't find a matching node. | ||
; | ||
@@ -340,3 +341,3 @@ function findNodeAt(node, start, end, test, base, state) { | ||
base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) { | ||
if (node.declaration) c(node.declaration, st); | ||
if (node.declaration) c(node.declaration, st, node.declaration.id ? "Statement" : "Expression"); | ||
if (node.source) c(node.source, st, "Expression"); | ||
@@ -343,0 +344,0 @@ }; |
@@ -6,3 +6,3 @@ { | ||
"main": "dist/acorn.js", | ||
"version": "2.4.0", | ||
"version": "2.5.0", | ||
"engines": { | ||
@@ -29,3 +29,3 @@ "node": ">=0.4.0" | ||
"scripts": { | ||
"prepublish": "node bin/build-acorn.js && node bin/without_eval > dist/acorn_csp.js", | ||
"prepublish": "node bin/build-acorn.js", | ||
"test": "node test/run.js" | ||
@@ -32,0 +32,0 @@ }, |
@@ -70,5 +70,6 @@ # Acorn | ||
- **allowReserved**: If `false`, using a reserved word will generate | ||
an error. Defaults to `true`. When given the value `"never"`, | ||
reserved words and keywords can also not be used as property names | ||
(as in Internet Explorer's old parser). | ||
an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher | ||
versions. When given the value `"never"`, reserved words and | ||
keywords can also not be used as property names (as in Internet | ||
Explorer's old parser). | ||
@@ -93,3 +94,4 @@ - **allowReturnOutsideFunction**: By default, a return statement at | ||
- **onToken**: If a function is passed for this option, each found | ||
token will be passed in same format as `tokenize()` returns. | ||
token will be passed in same format as tokens returned from | ||
`tokenizer().getToken()`. | ||
@@ -185,3 +187,3 @@ If array is passed, each found token is pushed to it. | ||
```javascript | ||
for (let token of acorn.tokenize(str)) { | ||
for (let token of acorn.tokenizer(str)) { | ||
// iterate over the tokens | ||
@@ -191,3 +193,3 @@ } | ||
// transform code to array of tokens: | ||
var tokens = [...acorn.tokenize(str)]; | ||
var tokens = [...acorn.tokenizer(str)]; | ||
``` | ||
@@ -226,16 +228,2 @@ | ||
#### Using Acorn in an environment with a Content Security Policy | ||
Some contexts, such as Chrome Web Apps, disallow run-time code evaluation. | ||
Acorn uses `new Function` to generate fast functions that test whether | ||
a word is in a given set, and will trigger a security error when used | ||
in a context with such a | ||
[Content Security Policy](http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too) | ||
(see [#90](https://github.com/marijnh/acorn/issues/90) and | ||
[#123](https://github.com/marijnh/acorn/issues/123)). | ||
The `dist/acorn_csp.js` file in the distribution (which is built | ||
by the `bin/without_eval` script) has the generated code inlined, and | ||
can thus run without evaluating anything. | ||
### dist/acorn_loose.js ### | ||
@@ -389,4 +377,2 @@ | ||
There is a proof-of-concept JSX plugin in the [`jsx` | ||
branch](https://github.com/marijnh/acorn/tree/jsx) branch of the | ||
Github repository. | ||
There is a proof-of-concept JSX plugin in the [`acorn-jsx`](https://github.com/RReverser/acorn-jsx) project. |
@@ -21,4 +21,2 @@ // A recursive descent parser operates by defining functions for all | ||
import {Parser} from "./state" | ||
import {reservedWords} from "./identifier" | ||
import {has} from "./util" | ||
@@ -35,3 +33,3 @@ const pp = Parser.prototype | ||
return | ||
let key = prop.key, name | ||
let {key} = prop, name | ||
switch (key.type) { | ||
@@ -42,3 +40,3 @@ case "Identifier": name = key.name; break | ||
} | ||
let kind = prop.kind | ||
let {kind} = prop | ||
if (this.options.ecmaVersion >= 6) { | ||
@@ -51,5 +49,5 @@ if (name === "__proto__" && kind === "init") { | ||
} | ||
let other | ||
if (has(propHash, name)) { | ||
other = propHash[name] | ||
name = "$" + name | ||
let other = propHash[name] | ||
if (other) { | ||
let isGetSet = kind !== "init" | ||
@@ -214,3 +212,4 @@ if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) | ||
let expr = this.parseExprAtom(refShorthandDefaultPos) | ||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr | ||
let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; | ||
if ((refShorthandDefaultPos && refShorthandDefaultPos.start) || skipArrowSubscripts) return expr | ||
return this.parseSubscripts(expr, startPos, startLoc) | ||
@@ -422,2 +421,4 @@ } | ||
this.raise(node.property.start, "The only valid meta property for new is new.target") | ||
if (!this.inFunction) | ||
this.raise(node.start, "new.target can only be used in functions") | ||
return this.finishNode(node, "MetaProperty") | ||
@@ -519,5 +520,4 @@ } | ||
if (isPattern) { | ||
if (this.isKeyword(prop.key.name) || | ||
(this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name))) || | ||
(!this.options.allowReserved && this.isReservedWord(prop.key.name))) | ||
if (this.keywords.test(prop.key.name) || | ||
(this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) | ||
this.raise(prop.key.start, "Binding " + prop.key.name) | ||
@@ -567,6 +567,4 @@ prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) | ||
node.params = this.parseBindingList(tt.parenR, false, false) | ||
let allowExpressionBody | ||
if (this.options.ecmaVersion >= 6) { | ||
if (this.options.ecmaVersion >= 6) | ||
node.generator = isGenerator | ||
} | ||
this.parseFunctionBody(node, false) | ||
@@ -587,4 +585,4 @@ return this.finishNode(node, "FunctionExpression") | ||
pp.parseFunctionBody = function(node, allowExpression) { | ||
let isExpression = allowExpression && this.type !== tt.braceL | ||
pp.parseFunctionBody = function(node, isArrowFunction) { | ||
let isExpression = isArrowFunction && this.type !== tt.braceL | ||
@@ -608,12 +606,22 @@ if (isExpression) { | ||
if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { | ||
let nameHash = {}, oldStrict = this.strict | ||
let oldStrict = this.strict | ||
this.strict = true | ||
if (node.id) | ||
this.checkLVal(node.id, true) | ||
for (let i = 0; i < node.params.length; i++) | ||
this.checkLVal(node.params[i], true, nameHash) | ||
this.checkParams(node); | ||
this.strict = oldStrict | ||
} else if (isArrowFunction) { | ||
this.checkParams(node); | ||
} | ||
} | ||
// Checks function params for various disallowed patterns such as using "eval" | ||
// or "arguments" and duplicate parameters. | ||
pp.checkParams = function(node) { | ||
let nameHash = {}; | ||
for (let i = 0; i < node.params.length; i++) | ||
this.checkLVal(node.params[i], true, nameHash) | ||
}; | ||
// Parses a comma-separated list of expressions, and returns them as | ||
@@ -654,6 +662,5 @@ // an array. `close` is the token type that ends the list, and | ||
if (!liberal && | ||
((!this.options.allowReserved && this.isReservedWord(this.value)) || | ||
(this.strict && reservedWords.strict(this.value)) && | ||
(this.options.ecmaVersion >= 6 || | ||
this.input.slice(this.start, this.end).indexOf("\\") == -1))) | ||
(this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && | ||
(this.options.ecmaVersion >= 6 || | ||
this.input.slice(this.start, this.end).indexOf("\\") == -1)) | ||
this.raise(this.start, "The keyword '" + this.value + "' is reserved") | ||
@@ -660,0 +667,0 @@ node.name = this.value |
@@ -10,49 +10,10 @@ // This is a trick taken from Esprima. It turns out that, on | ||
function makePredicate(words) { | ||
words = words.split(" ") | ||
let f = "", cats = [] | ||
out: for (let i = 0; i < words.length; ++i) { | ||
for (let j = 0; j < cats.length; ++j) | ||
if (cats[j][0].length == words[i].length) { | ||
cats[j].push(words[i]) | ||
continue out | ||
} | ||
cats.push([words[i]]) | ||
} | ||
function compareTo(arr) { | ||
if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";" | ||
f += "switch(str){" | ||
for (let i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":" | ||
f += "return true}return false;" | ||
} | ||
// When there are more than three length categories, an outer | ||
// switch first dispatches on the lengths, to save on comparisons. | ||
if (cats.length > 3) { | ||
cats.sort((a, b) => b.length - a.length) | ||
f += "switch(str.length){" | ||
for (let i = 0; i < cats.length; ++i) { | ||
let cat = cats[i] | ||
f += "case " + cat[0].length + ":" | ||
compareTo(cat) | ||
} | ||
f += "}" | ||
// Otherwise, simply generate a flat `switch` statement. | ||
} else { | ||
compareTo(words) | ||
} | ||
return new Function("str", f) | ||
} | ||
// Reserved word lists for various dialects of the language | ||
export const reservedWords = { | ||
3: makePredicate("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: makePredicate("class enum extends super const export import"), | ||
6: makePredicate("enum await"), | ||
strict: makePredicate("implements interface let package private protected public static yield"), | ||
strictBind: makePredicate("eval arguments") | ||
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" | ||
} | ||
@@ -65,4 +26,4 @@ | ||
export const keywords = { | ||
5: makePredicate(ecma5AndLessKeywords), | ||
6: makePredicate(ecma5AndLessKeywords + " let const class extends export import yield super") | ||
5: ecma5AndLessKeywords, | ||
6: ecma5AndLessKeywords + " let const class extends export import yield super" | ||
} | ||
@@ -69,0 +30,0 @@ |
@@ -23,3 +23,2 @@ // Acorn is a tiny, fast JavaScript parser written in JavaScript. | ||
import {Parser} from "./state" | ||
import {getOptions} from "./options" | ||
import "./parseutil" | ||
@@ -41,3 +40,3 @@ import "./statement" | ||
export const version = "2.4.0" | ||
export const version = "2.5.0" | ||
@@ -66,3 +65,3 @@ // The main exported interface (under `self.acorn` when in the | ||
// Acorn is organized as a tokenizer and a recursive-descent parser. | ||
// The `tokenize` export provides an interface to the tokenizer. | ||
// The `tokenizer` export provides an interface to the tokenizer. | ||
@@ -69,0 +68,0 @@ export function tokenizer(input, options) { |
import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from ".." | ||
export class LooseParser{ | ||
export class LooseParser { | ||
constructor(input, options) { | ||
@@ -46,12 +46,24 @@ this.toks = tokenizer(input, options) | ||
dummyNode(type) { | ||
let dummy = this.startNode() | ||
dummy.type = type | ||
dummy.end = dummy.start | ||
if (this.options.locations) | ||
dummy.loc.end = dummy.loc.start | ||
if (this.options.ranges) | ||
dummy.range[1] = dummy.start | ||
this.last = {type: tt.name, start: dummy.start, end: dummy.start, loc: dummy.loc} | ||
return dummy | ||
} | ||
dummyIdent() { | ||
let dummy = this.startNode() | ||
let dummy = this.dummyNode("Identifier") | ||
dummy.name = "✖" | ||
return this.finishNode(dummy, "Identifier") | ||
return dummy | ||
} | ||
dummyString() { | ||
let dummy = this.startNode() | ||
let dummy = this.dummyNode("Literal") | ||
dummy.value = dummy.raw = "✖" | ||
return this.finishNode(dummy, "Literal") | ||
return dummy | ||
} | ||
@@ -58,0 +70,0 @@ |
@@ -128,3 +128,2 @@ import {LooseParser} from "./state" | ||
this.expect(tt.parenR) | ||
clause.guard = null | ||
clause.body = this.parseBlock() | ||
@@ -363,3 +362,3 @@ node.handler = this.finishNode(clause, "CatchClause") | ||
node.specifiers = this.parseImportSpecifierList() | ||
node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString() | ||
node.source = this.eatContextual("from") && this.tok.type == tt.string ? this.parseExprAtom() : this.dummyString() | ||
if (elt) node.specifiers.unshift(elt) | ||
@@ -366,0 +365,0 @@ } |
import {types as tt} from "./tokentype" | ||
import {Parser} from "./state" | ||
import {reservedWords} from "./identifier" | ||
import {has} from "./util" | ||
@@ -73,2 +72,5 @@ | ||
} | ||
if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") | ||
this.unexpected(last.argument.start); | ||
} | ||
@@ -91,6 +93,10 @@ for (let i = 0; i < end; i++) { | ||
pp.parseRest = function() { | ||
pp.parseRest = function(allowNonIdent) { | ||
let node = this.startNode() | ||
this.next() | ||
node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected() | ||
// RestElement inside of a function parameter must be an identifier | ||
if (allowNonIdent) node.argument = this.type === tt.name ? this.parseIdent() : this.unexpected() | ||
else node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected() | ||
return this.finishNode(node, "RestElement") | ||
@@ -121,3 +127,3 @@ } | ||
pp.parseBindingList = function(close, allowEmpty, allowTrailingComma) { | ||
pp.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowNonIdent) { | ||
let elts = [], first = true | ||
@@ -132,3 +138,3 @@ while (!this.eat(close)) { | ||
} else if (this.type === tt.ellipsis) { | ||
let rest = this.parseRest() | ||
let rest = this.parseRest(allowNonIdent) | ||
this.parseBindingListItem(rest) | ||
@@ -168,7 +174,7 @@ elts.push(rest) | ||
case "Identifier": | ||
if (this.strict && (reservedWords.strictBind(expr.name) || reservedWords.strict(expr.name))) | ||
if (this.strict && this.reservedWordsStrictBind.test(expr.name)) | ||
this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode") | ||
if (checkClashes) { | ||
if (has(checkClashes, expr.name)) | ||
this.raise(expr.start, "Argument name clash in strict mode") | ||
this.raise(expr.start, "Argument name clash") | ||
checkClashes[expr.name] = true | ||
@@ -175,0 +181,0 @@ } |
@@ -24,7 +24,7 @@ import {has, isArray} from "./util" | ||
onTrailingComma: null, | ||
// By default, reserved words are not enforced. Disable | ||
// `allowReserved` to enforce them. When this option has the | ||
// value "never", reserved words and keywords can also not be | ||
// used as property names. | ||
allowReserved: true, | ||
// 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 | ||
@@ -46,5 +46,5 @@ // error. | ||
// cause Acorn to call that function with object in the same | ||
// format as tokenize() returns. Note that you are not | ||
// allowed to call the parser from the callback—that will | ||
// corrupt its internal state. | ||
// 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, | ||
@@ -95,2 +95,4 @@ // A function can be passed as `onComment` option, which will | ||
options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt] | ||
if (options.allowReserved == null) | ||
options.allowReserved = options.ecmaVersion >= 5 | ||
@@ -97,0 +99,0 @@ if (isArray(options.onToken)) { |
@@ -9,2 +9,6 @@ import {reservedWords, keywords} from "./identifier" | ||
function keywordRegexp(words) { | ||
return new RegExp("^(" + words.replace(/ /g, "|") + ")$") | ||
} | ||
export class Parser { | ||
@@ -14,4 +18,9 @@ constructor(options, input, startPos) { | ||
this.sourceFile = this.options.sourceFile | ||
this.isKeyword = keywords[this.options.ecmaVersion >= 6 ? 6 : 5] | ||
this.isReservedWord = reservedWords[this.options.ecmaVersion] | ||
this.keywords = keywordRegexp(keywords[this.options.ecmaVersion >= 6 ? 6 : 5]) | ||
let reserved = this.options.allowReserved ? "" : | ||
reservedWords[this.options.ecmaVersion] + (options.sourceType == "module" ? " await" : "") | ||
this.reservedWords = keywordRegexp(reserved) | ||
let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict | ||
this.reservedWordsStrict = keywordRegexp(reservedStrict) | ||
this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) | ||
this.input = String(input) | ||
@@ -76,2 +85,6 @@ | ||
// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them | ||
isKeyword(word) { return this.keywords.test(word) } | ||
isReservedWord(word) { return this.reservedWords.test(word) } | ||
extend(name, f) { | ||
@@ -78,0 +91,0 @@ this[name] = f(this[name]) |
@@ -259,7 +259,5 @@ import {types as tt} from "./tokentype" | ||
this.expect(tt.parenR) | ||
clause.guard = null | ||
clause.body = this.parseBlock() | ||
node.handler = this.finishNode(clause, "CatchClause") | ||
} | ||
node.guardedHandlers = empty | ||
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null | ||
@@ -419,3 +417,3 @@ if (!node.handler && !node.finalizer) | ||
this.expect(tt.parenL) | ||
node.params = this.parseBindingList(tt.parenR, false, false) | ||
node.params = this.parseBindingList(tt.parenR, false, false, true) | ||
} | ||
@@ -531,2 +529,9 @@ | ||
} else { | ||
// check for keywords used as local names | ||
for (let i = 0; i < node.specifiers.length; i++) { | ||
if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { | ||
this.unexpected(node.specifiers[i].local.start) | ||
} | ||
} | ||
node.source = null | ||
@@ -533,0 +538,0 @@ } |
@@ -379,3 +379,3 @@ import {isIdentifierStart, isIdentifierChar} from "./identifier" | ||
function tryCreateRegexp(src, flags, throwErrorAt) { | ||
function tryCreateRegexp(src, flags, throwErrorAt, parser) { | ||
try { | ||
@@ -385,4 +385,4 @@ return new RegExp(src, flags); | ||
if (throwErrorAt !== undefined) { | ||
if (e instanceof SyntaxError) this.raise(throwErrorAt, "Error parsing regular expression: " + e.message) | ||
this.raise(e) | ||
if (e instanceof SyntaxError) parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message) | ||
throw e | ||
} | ||
@@ -427,3 +427,3 @@ } | ||
// be replaced by `[x-b]` which throws an error. | ||
tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, (match, code, offset) => { | ||
tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, (_match, code, offset) => { | ||
code = Number("0x" + code) | ||
@@ -441,3 +441,3 @@ if (code > 0x10FFFF) this.raise(start + offset + 3, "Code point out of bounds") | ||
if (!isRhino) { | ||
tryCreateRegexp(tmp, undefined, start); | ||
tryCreateRegexp(tmp, undefined, start, this); | ||
// Get a regular expression object for this pattern-flag pair, or `null` in | ||
@@ -683,5 +683,5 @@ // case the current environment doesn't support the flags it uses. | ||
let type = tt.name | ||
if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.isKeyword(word)) | ||
if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) | ||
type = keywordTypes[word] | ||
return this.finishToken(type, word) | ||
} |
@@ -15,2 +15,7 @@ // ## Token types | ||
// | ||
// 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 | ||
@@ -113,3 +118,3 @@ // to know when parsing a label, in order to allow or disallow | ||
kw("default", beforeExpr) | ||
kw("do", {isLoop: true}) | ||
kw("do", {isLoop: true, beforeExpr: true}) | ||
kw("else", beforeExpr) | ||
@@ -116,0 +121,0 @@ kw("finally") |
@@ -307,3 +307,3 @@ // AST walker module for Mozilla Parser API compatible trees | ||
base.ExportNamedDeclaration = base.ExportDefaultDeclaration = (node, st, c) => { | ||
if (node.declaration) c(node.declaration, st) | ||
if (node.declaration) c(node.declaration, st, node.declaration.id ? "Statement" : "Expression") | ||
if (node.source) c(node.source, st, "Expression") | ||
@@ -310,0 +310,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Uses eval
Supply chain riskPackage uses eval() which is a dangerous function. This prevents the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
12
0
366135
42
8649
373