move acorn into vendor
This commit is contained in:
parent
2ff1a5d98b
commit
2c39d406d1
221
lib/acorn/acorn.js → vendor/acorn/acorn.js
vendored
221
lib/acorn/acorn.js → vendor/acorn/acorn.js
vendored
@ -122,7 +122,7 @@
|
|||||||
preserveParens: false,
|
preserveParens: false,
|
||||||
plugins: {},
|
plugins: {},
|
||||||
// Babel-specific options
|
// Babel-specific options
|
||||||
transformers: {},
|
features: {},
|
||||||
strictMode: false
|
strictMode: false
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -911,7 +911,7 @@
|
|||||||
var width = 1;
|
var width = 1;
|
||||||
var next = this.input.charCodeAt(this.pos + 1);
|
var next = this.input.charCodeAt(this.pos + 1);
|
||||||
|
|
||||||
if (this.options.transformers["es7.exponentiationOperator"] && next === 42) { // '*'
|
if (next === 42) { // '*'
|
||||||
width++;
|
width++;
|
||||||
next = this.input.charCodeAt(this.pos + 2);
|
next = this.input.charCodeAt(this.pos + 2);
|
||||||
type = tt.exponent;
|
type = tt.exponent;
|
||||||
@ -1838,6 +1838,17 @@
|
|||||||
this.raise(this.start, "'import' and 'export' may only appear at the top level");
|
this.raise(this.start, "'import' and 'export' may only appear at the top level");
|
||||||
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node);
|
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node);
|
||||||
|
|
||||||
|
case tt.name:
|
||||||
|
if (this.options.features["es7.asyncFunctions"] && this.value === "async") {
|
||||||
|
// check to see if `function ` appears after this token, this is
|
||||||
|
// pretty hacky
|
||||||
|
if (this.input.slice(this.pos + 1, this.pos + 10) === "function ") {
|
||||||
|
this.next();
|
||||||
|
this.expect(tt._function);
|
||||||
|
return this.parseFunction(node, true, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the statement does not start with a statement keyword or a
|
// If the statement does not start with a statement keyword or a
|
||||||
// brace, it's an ExpressionStatement or LabeledStatement. We
|
// brace, it's an ExpressionStatement or LabeledStatement. We
|
||||||
// simply start parsing an expression, and afterwards, if the
|
// simply start parsing an expression, and afterwards, if the
|
||||||
@ -2346,8 +2357,51 @@
|
|||||||
if (this.inGenerator) unexpected();
|
if (this.inGenerator) unexpected();
|
||||||
|
|
||||||
case tt.name:
|
case tt.name:
|
||||||
|
if (this.value === "super") {
|
||||||
|
var node = this.startNode();
|
||||||
|
this.next();
|
||||||
|
return this.finishNode(node, "SuperExpression");
|
||||||
|
}
|
||||||
|
|
||||||
var start = this.currentPos();
|
var start = this.currentPos();
|
||||||
|
var node = this.startNode();
|
||||||
var id = this.parseIdent(this.type !== tt.name);
|
var id = this.parseIdent(this.type !== tt.name);
|
||||||
|
|
||||||
|
//
|
||||||
|
if (this.options.features["es7.asyncFunctions"]) {
|
||||||
|
// async functions!
|
||||||
|
if (id.name === "async") {
|
||||||
|
// arrow functions
|
||||||
|
if (this.type === tt.parenL) {
|
||||||
|
var expr = this.parseParenAndDistinguishExpression(start, true);
|
||||||
|
if (expr.type === "ArrowFunctionExpression") {
|
||||||
|
return expr;
|
||||||
|
} else {
|
||||||
|
node.callee = id;
|
||||||
|
if (expr.type === "SequenceExpression") {
|
||||||
|
node.arguments = expr.expressions;
|
||||||
|
} else {
|
||||||
|
node.arguments = [expr];
|
||||||
|
}
|
||||||
|
return this.parseSubscripts(this.finishNode(node, "CallExpression"), start);
|
||||||
|
}
|
||||||
|
} else if (this.type === tt.name) {
|
||||||
|
id = this.parseIdent();
|
||||||
|
this.expect(tt.arrow);
|
||||||
|
return this.parseArrowExpression(node, [id], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal functions
|
||||||
|
if (this.type === tt._function && !this.canInsertSemicolon()) {
|
||||||
|
this.next();
|
||||||
|
return this.parseFunction(node, false, false, true);
|
||||||
|
}
|
||||||
|
} else if (id.name === "await") {
|
||||||
|
if (this.inAsync) return this.parseAwait(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
if (!this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
if (!this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||||
return this.parseArrowExpression(this.startNodeAt(start), [id]);
|
return this.parseArrowExpression(this.startNodeAt(start), [id]);
|
||||||
}
|
}
|
||||||
@ -2376,7 +2430,7 @@
|
|||||||
var node = this.startNode();
|
var node = this.startNode();
|
||||||
this.next();
|
this.next();
|
||||||
// check whether this is array comprehension or regular array
|
// check whether this is array comprehension or regular array
|
||||||
if (this.options.transformers["es7.comprehensions"] && this.type === tt._for) {
|
if ((this.options.features["es7.comprehensions"] || this.options.ecmaVersion >= 7) && this.type === tt._for) {
|
||||||
return this.parseComprehension(node, false);
|
return this.parseComprehension(node, false);
|
||||||
}
|
}
|
||||||
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
|
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
|
||||||
@ -2412,12 +2466,13 @@
|
|||||||
return this.finishNode(node, "Literal");
|
return this.finishNode(node, "Literal");
|
||||||
};
|
};
|
||||||
|
|
||||||
pp.parseParenAndDistinguishExpression = function() {
|
pp.parseParenAndDistinguishExpression = function(start, isAsync) {
|
||||||
var start = this.currentPos(), val;
|
start = start || this.currentPos();
|
||||||
|
var val;
|
||||||
if (this.options.ecmaVersion >= 6) {
|
if (this.options.ecmaVersion >= 6) {
|
||||||
this.next();
|
this.next();
|
||||||
|
|
||||||
if (this.options.transformers["es7.comprehensions"] && this.type === tt._for) {
|
if ((this.options.features["es7.comprehensions"] || this.options.ecmaVersion >= 7) && this.type === tt._for) {
|
||||||
return this.parseComprehension(this.startNodeAt(start), true);
|
return this.parseComprehension(this.startNodeAt(start), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2442,7 +2497,7 @@
|
|||||||
|
|
||||||
if (!this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
if (!this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||||
if (innerParenStart) this.unexpected(innerParenStart);
|
if (innerParenStart) this.unexpected(innerParenStart);
|
||||||
return this.parseArrowExpression(this.startNodeAt(start), exprList);
|
return this.parseParenArrowList(start, exprList, isAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exprList.length) this.unexpected(this.lastTokStart);
|
if (!exprList.length) this.unexpected(this.lastTokStart);
|
||||||
@ -2469,6 +2524,10 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pp.parseParenArrowList = function (start, exprList, isAsync) {
|
||||||
|
return this.parseArrowExpression(this.startNodeAt(start), exprList, isAsync);
|
||||||
|
};
|
||||||
|
|
||||||
pp.parseParenItem = function (node, start) {
|
pp.parseParenItem = function (node, start) {
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
@ -2528,8 +2587,8 @@
|
|||||||
if (this.afterTrailingComma(tt.braceR)) break;
|
if (this.afterTrailingComma(tt.braceR)) break;
|
||||||
} else first = false;
|
} else first = false;
|
||||||
|
|
||||||
var prop = this.startNode(), isGenerator, start;
|
var prop = this.startNode(), isGenerator, isAsync, start;
|
||||||
if (this.options.transformers["es7.objectRestSpread"] && this.type === tt.ellipsis) {
|
if (this.options.features["es7.objectRestSpread"] && this.type === tt.ellipsis) {
|
||||||
prop = this.parseSpread();
|
prop = this.parseSpread();
|
||||||
prop.type = "SpreadProperty";
|
prop.type = "SpreadProperty";
|
||||||
node.properties.push(prop);
|
node.properties.push(prop);
|
||||||
@ -2545,7 +2604,27 @@
|
|||||||
isGenerator = this.eat(tt.star);
|
isGenerator = this.eat(tt.star);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.options.features["es7.asyncFunctions"] && this.isContextual("async")) {
|
||||||
|
if (isGenerator || isPattern) this.unexpected();
|
||||||
|
|
||||||
|
var asyncId = this.parseIdent();
|
||||||
|
if (this.type === tt.colon || this.type === tt.parenL) {
|
||||||
|
prop.key = asyncId;
|
||||||
|
} else {
|
||||||
|
isAsync = true;
|
||||||
this.parsePropertyName(prop);
|
this.parsePropertyName(prop);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.parsePropertyName(prop);
|
||||||
|
}
|
||||||
|
this.parseObjPropValue(prop, start, isGenerator, isAsync, isPattern, refShorthandDefaultPos);
|
||||||
|
this.checkPropClash(prop, propHash);
|
||||||
|
node.properties.push(this.finishNode(prop, "Property"));
|
||||||
|
}
|
||||||
|
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
|
||||||
|
};
|
||||||
|
|
||||||
|
pp.parseObjPropValue = function (prop, start, isGenerator, isAsync, isPattern, refShorthandDefaultPos) {
|
||||||
if (this.eat(tt.colon)) {
|
if (this.eat(tt.colon)) {
|
||||||
prop.value = isPattern ? this.parseMaybeDefault() : this.parseMaybeAssign(false, refShorthandDefaultPos);
|
prop.value = isPattern ? this.parseMaybeDefault() : this.parseMaybeAssign(false, refShorthandDefaultPos);
|
||||||
prop.kind = "init";
|
prop.kind = "init";
|
||||||
@ -2553,11 +2632,11 @@
|
|||||||
if (isPattern) this.unexpected();
|
if (isPattern) this.unexpected();
|
||||||
prop.kind = "init";
|
prop.kind = "init";
|
||||||
prop.method = true;
|
prop.method = true;
|
||||||
prop.value = this.parseMethod(isGenerator);
|
prop.value = this.parseMethod(isGenerator, isAsync);
|
||||||
} else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
|
} else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
|
||||||
(prop.key.name === "get" || prop.key.name === "set") &&
|
(prop.key.name === "get" || prop.key.name === "set") &&
|
||||||
(this.type != tt.comma && this.type != tt.braceR)) {
|
(this.type != tt.comma && this.type != tt.braceR)) {
|
||||||
if (isGenerator || isPattern) this.unexpected();
|
if (isGenerator || isAsync || isPattern) this.unexpected();
|
||||||
prop.kind = prop.key.name;
|
prop.kind = prop.key.name;
|
||||||
this.parsePropertyName(prop);
|
this.parsePropertyName(prop);
|
||||||
prop.value = this.parseMethod(false);
|
prop.value = this.parseMethod(false);
|
||||||
@ -2574,18 +2653,13 @@
|
|||||||
}
|
}
|
||||||
prop.shorthand = true;
|
prop.shorthand = true;
|
||||||
} else this.unexpected();
|
} else this.unexpected();
|
||||||
|
|
||||||
this.checkPropClash(prop, propHash);
|
|
||||||
node.properties.push(this.finishNode(prop, "Property"));
|
|
||||||
}
|
|
||||||
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pp.parsePropertyName = function(prop) {
|
pp.parsePropertyName = function(prop) {
|
||||||
if (this.options.ecmaVersion >= 6) {
|
if (this.options.ecmaVersion >= 6) {
|
||||||
if (this.eat(tt.bracketL)) {
|
if (this.eat(tt.bracketL)) {
|
||||||
prop.computed = true;
|
prop.computed = true;
|
||||||
prop.key = this.parseExpression();
|
prop.key = this.parseMaybeAssign();
|
||||||
this.expect(tt.bracketR);
|
this.expect(tt.bracketR);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -2597,19 +2671,22 @@
|
|||||||
|
|
||||||
// Initialize empty function node.
|
// Initialize empty function node.
|
||||||
|
|
||||||
pp.initFunction = function(node) {
|
pp.initFunction = function(node, isAsync) {
|
||||||
node.id = null;
|
node.id = null;
|
||||||
if (this.options.ecmaVersion >= 6) {
|
if (this.options.ecmaVersion >= 6) {
|
||||||
node.generator = false;
|
node.generator = false;
|
||||||
node.expression = false;
|
node.expression = false;
|
||||||
}
|
}
|
||||||
|
if (this.options.features["es7.asyncFunctions"]) {
|
||||||
|
node.async = !!isAsync;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse a function declaration or literal (depending on the
|
// Parse a function declaration or literal (depending on the
|
||||||
// `isStatement` parameter).
|
// `isStatement` parameter).
|
||||||
|
|
||||||
pp.parseFunction = function(node, isStatement, allowExpressionBody) {
|
pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
|
||||||
this.initFunction(node);
|
this.initFunction(node, isAsync);
|
||||||
if (this.options.ecmaVersion >= 6) {
|
if (this.options.ecmaVersion >= 6) {
|
||||||
node.generator = this.eat(tt.star);
|
node.generator = this.eat(tt.star);
|
||||||
}
|
}
|
||||||
@ -2628,9 +2705,9 @@
|
|||||||
|
|
||||||
// Parse object or class method.
|
// Parse object or class method.
|
||||||
|
|
||||||
pp.parseMethod = function(isGenerator) {
|
pp.parseMethod = function(isGenerator, isAsync) {
|
||||||
var node = this.startNode();
|
var node = this.startNode();
|
||||||
this.initFunction(node);
|
this.initFunction(node, isAsync);
|
||||||
this.expect(tt.parenL);
|
this.expect(tt.parenL);
|
||||||
node.params = this.parseBindingList(tt.parenR, false, false);
|
node.params = this.parseBindingList(tt.parenR, false, false);
|
||||||
var allowExpressionBody;
|
var allowExpressionBody;
|
||||||
@ -2646,8 +2723,8 @@
|
|||||||
|
|
||||||
// Parse arrow function expression with given parameters.
|
// Parse arrow function expression with given parameters.
|
||||||
|
|
||||||
pp.parseArrowExpression = function(node, params) {
|
pp.parseArrowExpression = function(node, params, isAsync) {
|
||||||
this.initFunction(node);
|
this.initFunction(node, isAsync);
|
||||||
node.params = this.toAssignableList(params, true);
|
node.params = this.toAssignableList(params, true);
|
||||||
this.parseFunctionBody(node, true);
|
this.parseFunctionBody(node, true);
|
||||||
return this.finishNode(node, "ArrowFunctionExpression");
|
return this.finishNode(node, "ArrowFunctionExpression");
|
||||||
@ -2658,6 +2735,8 @@
|
|||||||
pp.parseFunctionBody = function(node, allowExpression) {
|
pp.parseFunctionBody = function(node, allowExpression) {
|
||||||
var isExpression = allowExpression && this.type !== tt.braceL;
|
var isExpression = allowExpression && this.type !== tt.braceL;
|
||||||
|
|
||||||
|
var oldInAsync = this.inAsync;
|
||||||
|
this.inAsync = node.async;
|
||||||
if (isExpression) {
|
if (isExpression) {
|
||||||
node.body = this.parseMaybeAssign();
|
node.body = this.parseMaybeAssign();
|
||||||
node.expression = true;
|
node.expression = true;
|
||||||
@ -2670,6 +2749,7 @@
|
|||||||
node.expression = false;
|
node.expression = false;
|
||||||
this.inFunction = oldInFunc; this.inGenerator = oldInGen; this.labels = oldLabels;
|
this.inFunction = oldInFunc; this.inGenerator = oldInGen; this.labels = oldLabels;
|
||||||
}
|
}
|
||||||
|
this.inAsync = oldInAsync;
|
||||||
|
|
||||||
// If this is a strict mode function, verify that argument names
|
// If this is a strict mode function, verify that argument names
|
||||||
// are not repeated, and it does not try to bind the words `eval`
|
// are not repeated, and it does not try to bind the words `eval`
|
||||||
@ -2696,7 +2776,7 @@
|
|||||||
while (!this.eat(tt.braceR)) {
|
while (!this.eat(tt.braceR)) {
|
||||||
if (this.eat(tt.semi)) continue;
|
if (this.eat(tt.semi)) continue;
|
||||||
var method = this.startNode();
|
var method = this.startNode();
|
||||||
var isGenerator = this.eat(tt.star);
|
var isGenerator = this.eat(tt.star), isAsync;
|
||||||
this.parsePropertyName(method);
|
this.parsePropertyName(method);
|
||||||
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
||||||
method.key.name === "static") {
|
method.key.name === "static") {
|
||||||
@ -2707,21 +2787,35 @@
|
|||||||
} else {
|
} else {
|
||||||
method['static'] = false;
|
method['static'] = false;
|
||||||
}
|
}
|
||||||
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
if (this.options.features["es7.asyncFunctions"] && this.type !== tt.parenL &&
|
||||||
(method.key.name === "get" || method.key.name === "set")) {
|
!method.computed && method.key.type === "Identifier" && method.key.name === "async") {
|
||||||
if (isGenerator) this.unexpected();
|
isAsync = true;
|
||||||
|
this.parsePropertyName(method);
|
||||||
|
}
|
||||||
|
method.kind = "method";
|
||||||
|
if (!method.computed && !isGenerator) {
|
||||||
|
if (method.key.type === "Identifier") {
|
||||||
|
if (this.type !== tt.parenL && (method.key.name === "get" || method.key.name === "set")) {
|
||||||
method.kind = method.key.name;
|
method.kind = method.key.name;
|
||||||
this.parsePropertyName(method);
|
this.parsePropertyName(method);
|
||||||
} else {
|
} else if (!method['static'] && method.key.name === "constructor") {
|
||||||
method.kind = "";
|
method.kind = "constructor";
|
||||||
}
|
}
|
||||||
method.value = this.parseMethod(isGenerator);
|
} else if (!method['static'] && method.key.type === "Literal" && method.key.value === "constructor") {
|
||||||
classBody.body.push(this.finishNode(method, "MethodDefinition"));
|
method.kind = "constructor";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.parseClassMethod(classBody, method, isGenerator, isAsync);
|
||||||
}
|
}
|
||||||
node.body = this.finishNode(classBody, "ClassBody");
|
node.body = this.finishNode(classBody, "ClassBody");
|
||||||
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
|
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
|
||||||
|
method.value = this.parseMethod(isGenerator, isAsync);
|
||||||
|
classBody.body.push(this.finishNode(method, "MethodDefinition"));
|
||||||
|
};
|
||||||
|
|
||||||
pp.parseClassId = function (node, isStatement) {
|
pp.parseClassId = function (node, isStatement) {
|
||||||
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;
|
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;
|
||||||
};
|
};
|
||||||
@ -2788,6 +2882,7 @@
|
|||||||
if (this.eat(tt.star)) {
|
if (this.eat(tt.star)) {
|
||||||
this.expectContextual("from");
|
this.expectContextual("from");
|
||||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
||||||
|
this.semicolon();
|
||||||
return this.finishNode(node, "ExportAllDeclaration");
|
return this.finishNode(node, "ExportAllDeclaration");
|
||||||
}
|
}
|
||||||
if (this.eat(tt._default)) { // export default ...;
|
if (this.eat(tt._default)) { // export default ...;
|
||||||
@ -2803,7 +2898,7 @@
|
|||||||
return this.finishNode(node, "ExportDefaultDeclaration");
|
return this.finishNode(node, "ExportDefaultDeclaration");
|
||||||
}
|
}
|
||||||
// export var|const|let|function|class ...;
|
// export var|const|let|function|class ...;
|
||||||
if (this.type.keyword) {
|
if (this.type.keyword || (this.options.features["es7.asyncFunctions"] && this.isContextual("async"))) {
|
||||||
node.declaration = this.parseStatement(true);
|
node.declaration = this.parseStatement(true);
|
||||||
node.specifiers = [];
|
node.specifiers = [];
|
||||||
node.source = null;
|
node.source = null;
|
||||||
@ -2844,13 +2939,13 @@
|
|||||||
|
|
||||||
pp.parseImport = function(node) {
|
pp.parseImport = function(node) {
|
||||||
this.next();
|
this.next();
|
||||||
|
node.specifiers = [];
|
||||||
// import '...';
|
// import '...';
|
||||||
if (this.type === tt.string) {
|
if (this.type === tt.string) {
|
||||||
node.specifiers = [];
|
|
||||||
node.source = this.parseExprAtom();
|
node.source = this.parseExprAtom();
|
||||||
node.kind = "";
|
node.kind = "";
|
||||||
} else {
|
} else {
|
||||||
node.specifiers = this.parseImportSpecifiers();
|
this.parseImportSpecifiers(node);
|
||||||
this.expectContextual("from");
|
this.expectContextual("from");
|
||||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
||||||
}
|
}
|
||||||
@ -2860,24 +2955,22 @@
|
|||||||
|
|
||||||
// Parses a comma-separated list of module imports.
|
// Parses a comma-separated list of module imports.
|
||||||
|
|
||||||
pp.parseImportSpecifiers = function() {
|
pp.parseImportSpecifiers = function(node) {
|
||||||
var nodes = [], first = true;
|
var first = true;
|
||||||
if (this.type === tt.name) {
|
if (this.type === tt.name) {
|
||||||
// import defaultObj, { x, y as z } from '...'
|
// import defaultObj, { x, y as z } from '...'
|
||||||
var node = this.startNode();
|
var start = this.currentPos();
|
||||||
node.local = this.parseIdent();
|
node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdent(), start));
|
||||||
this.checkLVal(node.local, true);
|
if (!this.eat(tt.comma)) return;
|
||||||
nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
|
|
||||||
if (!this.eat(tt.comma)) return nodes;
|
|
||||||
}
|
}
|
||||||
if (this.type === tt.star) {
|
if (this.type === tt.star) {
|
||||||
var node = this.startNode();
|
var specifier = this.startNode();
|
||||||
this.next();
|
this.next();
|
||||||
this.expectContextual("as");
|
this.expectContextual("as");
|
||||||
node.local = this.parseIdent();
|
specifier.local = this.parseIdent();
|
||||||
this.checkLVal(node.local, true);
|
this.checkLVal(specifier.local, true);
|
||||||
nodes.push(this.finishNode(node, "ImportNamespaceSpecifier"));
|
node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier"));
|
||||||
return nodes;
|
return;
|
||||||
}
|
}
|
||||||
this.expect(tt.braceL);
|
this.expect(tt.braceL);
|
||||||
while (!this.eat(tt.braceR)) {
|
while (!this.eat(tt.braceR)) {
|
||||||
@ -2886,13 +2979,19 @@
|
|||||||
if (this.afterTrailingComma(tt.braceR)) break;
|
if (this.afterTrailingComma(tt.braceR)) break;
|
||||||
} else first = false;
|
} else first = false;
|
||||||
|
|
||||||
var node = this.startNode();
|
var specifier = this.startNode();
|
||||||
node.imported = this.parseIdent(true);
|
specifier.imported = this.parseIdent(true);
|
||||||
node.local = this.eatContextual("as") ? this.parseIdent() : node.imported;
|
specifier.local = this.eatContextual("as") ? this.parseIdent() : specifier.imported;
|
||||||
this.checkLVal(node.local, true);
|
this.checkLVal(specifier.local, true);
|
||||||
nodes.push(this.finishNode(node, "ImportSpecifier"));
|
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
||||||
}
|
}
|
||||||
return nodes;
|
};
|
||||||
|
|
||||||
|
pp.parseImportSpecifierDefault = function (id, start) {
|
||||||
|
var node = this.startNodeAt(start);
|
||||||
|
node.local = id;
|
||||||
|
this.checkLVal(node.local, true);
|
||||||
|
return this.finishNode(node, "ImportDefaultSpecifier");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parses yield expression inside generator.
|
// Parses yield expression inside generator.
|
||||||
@ -2910,6 +3009,17 @@
|
|||||||
return this.finishNode(node, "YieldExpression");
|
return this.finishNode(node, "YieldExpression");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Parses await expression inside async function.
|
||||||
|
|
||||||
|
pp.parseAwait = function (node) {
|
||||||
|
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
|
||||||
|
this.unexpected();
|
||||||
|
}
|
||||||
|
node.all = this.eat(tt.star);
|
||||||
|
node.argument = this.parseMaybeAssign(true);
|
||||||
|
return this.finishNode(node, "AwaitExpression");
|
||||||
|
};
|
||||||
|
|
||||||
// Parses array and generator comprehensions.
|
// Parses array and generator comprehensions.
|
||||||
|
|
||||||
pp.parseComprehension = function(node, isGenerator) {
|
pp.parseComprehension = function(node, isGenerator) {
|
||||||
@ -2931,4 +3041,9 @@
|
|||||||
node.generator = isGenerator;
|
node.generator = isGenerator;
|
||||||
return this.finishNode(node, "ComprehensionExpression");
|
return this.finishNode(node, "ComprehensionExpression");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// init plugins
|
||||||
|
|
||||||
|
require("./plugins/flow");
|
||||||
|
require("./plugins/jsx");
|
||||||
});
|
});
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import acorn from "../../acorn";
|
var acorn = require("../acorn");
|
||||||
|
|
||||||
var pp = acorn.Parser.prototype;
|
var pp = acorn.Parser.prototype;
|
||||||
var tt = acorn.tokTypes;
|
var tt = acorn.tokTypes;
|
||||||
@ -669,6 +669,54 @@ acorn.plugins.flow = function (instance) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
instance.extend("readToken", function(inner) {
|
||||||
|
return function(code) {
|
||||||
|
if (this.inType && (code === 62 || code === 60)) {
|
||||||
|
return this.finishOp(tt.relational, 1);
|
||||||
|
} else {
|
||||||
|
return inner.call(this, code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.extend("parseParenArrowList", function (inner) {
|
||||||
|
return function (start, exprList, isAsync) {
|
||||||
|
for (var i = 0; i < exprList.length; i++) {
|
||||||
|
var listItem = exprList[i];
|
||||||
|
if (listItem.type === "TypeCastExpression") {
|
||||||
|
var expr = listItem.expression;
|
||||||
|
expr.typeAnnotation = listItem.typeAnnotation;
|
||||||
|
exprList[i] = expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inner.call(this, start, exprList, isAsync);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.extend("parseClassMethod", function (inner) {
|
||||||
|
return function (classBody, method, isGenerator, isAsync) {
|
||||||
|
var classProperty = false;
|
||||||
|
|
||||||
|
if (this.type === tt.colon) {
|
||||||
|
method.typeAnnotation = this.flow_parseTypeAnnotation();
|
||||||
|
classProperty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classProperty) {
|
||||||
|
this.semicolon();
|
||||||
|
classBody.body.push(this.finishNode(method, "ClassProperty"));
|
||||||
|
} else {
|
||||||
|
var typeParameters;
|
||||||
|
if (this.isRelational("<")) {
|
||||||
|
typeParameters = this.flow_parseTypeParameterDeclaration();
|
||||||
|
}
|
||||||
|
method.value = this.parseMethod(isGenerator, isAsync);
|
||||||
|
method.value.typeParameters = typeParameters;
|
||||||
|
classBody.body.push(this.finishNode(method, "MethodDefinition"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
instance.extend("parseClassSuper", function (inner) {
|
instance.extend("parseClassSuper", function (inner) {
|
||||||
return function (node, isStatement) {
|
return function (node, isStatement) {
|
||||||
inner.call(this, node, isStatement);
|
inner.call(this, node, isStatement);
|
||||||
@ -692,6 +740,18 @@ acorn.plugins.flow = function (instance) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
instance.extend("parseObjPropValue", function (inner) {
|
||||||
|
return function (prop) {
|
||||||
|
var typeParameters;
|
||||||
|
if (this.isRelational("<")) {
|
||||||
|
typeParameters = this.flow_parseTypeParameterDeclaration();
|
||||||
|
if (this.type !== tt.parenL) this.unexpected();
|
||||||
|
}
|
||||||
|
inner.apply(this, arguments);
|
||||||
|
prop.value.typeParameters = typeParameters;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
instance.extend("parseAssignableListItemTypes", function (inner) {
|
instance.extend("parseAssignableListItemTypes", function (inner) {
|
||||||
return function (param) {
|
return function (param) {
|
||||||
if (this.eat(tt.question)) {
|
if (this.eat(tt.question)) {
|
||||||
@ -705,6 +765,24 @@ acorn.plugins.flow = function (instance) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
instance.extend("parseImportSpecifiers", function (inner) {
|
||||||
|
return function (node) {
|
||||||
|
node.isType = false;
|
||||||
|
if (this.isContextual("type")) {
|
||||||
|
var start = this.currentPos();
|
||||||
|
var typeId = this.parseIdent();
|
||||||
|
if ((this.type === tt.name && this.value !== "from") || this.type === tt.braceL || this.type === tt.star) {
|
||||||
|
node.isType = true;
|
||||||
|
} else {
|
||||||
|
node.specifiers.push(this.parseImportSpecifierDefault(typeId, start));
|
||||||
|
if (this.isContextual("from")) return;
|
||||||
|
this.eat(tt.comma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inner.call(this, node);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// function foo<T>() {}
|
// function foo<T>() {}
|
||||||
instance.extend("parseFunctionParams", function (inner) {
|
instance.extend("parseFunctionParams", function (inner) {
|
||||||
return function (node) {
|
return function (node) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import acorn from "../../acorn";
|
var acorn = require("../acorn");
|
||||||
|
|
||||||
var tt = acorn.tokTypes;
|
var tt = acorn.tokTypes;
|
||||||
var tc = acorn.tokContexts;
|
var tc = acorn.tokContexts;
|
||||||
@ -614,6 +614,7 @@ acorn.plugins.jsx = function(instance) {
|
|||||||
|
|
||||||
instance.extend("readToken", function(inner) {
|
instance.extend("readToken", function(inner) {
|
||||||
return function(code) {
|
return function(code) {
|
||||||
|
if (!this.inType) {
|
||||||
var context = this.curContext();
|
var context = this.curContext();
|
||||||
|
|
||||||
if (context === tc.j_expr) return this.jsx_readToken();
|
if (context === tc.j_expr) return this.jsx_readToken();
|
||||||
@ -634,6 +635,8 @@ acorn.plugins.jsx = function(instance) {
|
|||||||
++this.pos;
|
++this.pos;
|
||||||
return this.finishToken(tt.jsxTagStart);
|
return this.finishToken(tt.jsxTagStart);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return inner.call(this, code);
|
return inner.call(this, code);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -33,7 +33,7 @@
|
|||||||
else callback("fail", test.code,
|
else callback("fail", test.code,
|
||||||
"Expected error message: " + test.error + "\nGot error message: " + e.message);
|
"Expected error message: " + test.error + "\nGot error message: " + e.message);
|
||||||
} else {
|
} else {
|
||||||
callback("error", test.code, e.message || e.toString());
|
callback("error", test.code, e.stack || e.toString());
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
14
lib/acorn/test/run.js → vendor/acorn/test/run.js
vendored
14
lib/acorn/test/run.js → vendor/acorn/test/run.js
vendored
@ -5,6 +5,9 @@
|
|||||||
driver = require("./driver.js");
|
driver = require("./driver.js");
|
||||||
require("./tests.js");
|
require("./tests.js");
|
||||||
require("./tests-harmony.js");
|
require("./tests-harmony.js");
|
||||||
|
require("./tests-flow.js");
|
||||||
|
require("./tests-babel.js");
|
||||||
|
require("./tests-jsx.js");
|
||||||
} else {
|
} else {
|
||||||
driver = window;
|
driver = window;
|
||||||
}
|
}
|
||||||
@ -49,17 +52,6 @@
|
|||||||
config: {
|
config: {
|
||||||
parse: (typeof require === "undefined" ? window.acorn : require("../acorn.js")).parse
|
parse: (typeof require === "undefined" ? window.acorn : require("../acorn.js")).parse
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Loose: {
|
|
||||||
config: {
|
|
||||||
parse: (typeof require === "undefined" ? window.acorn : require("../acorn_loose")).parse_dammit,
|
|
||||||
loose: true,
|
|
||||||
filter: function (test) {
|
|
||||||
var opts = test.options || {};
|
|
||||||
if (opts.loose === false) return false;
|
|
||||||
return (opts.ecmaVersion || 5) <= 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
2057
vendor/acorn/test/tests-babel.js
vendored
Normal file
2057
vendor/acorn/test/tests-babel.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11125
vendor/acorn/test/tests-flow.js
vendored
Normal file
11125
vendor/acorn/test/tests-flow.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -6560,7 +6560,7 @@ test("class A {get() {}}", {
|
|||||||
end: {line: 1, column: 17}
|
end: {line: 1, column: 17}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 9},
|
start: {line: 1, column: 9},
|
||||||
@ -6632,7 +6632,7 @@ test("class A { static get() {}}", {
|
|||||||
end: {line: 1, column: 25}
|
end: {line: 1, column: 25}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 10},
|
start: {line: 1, column: 10},
|
||||||
@ -7027,7 +7027,7 @@ test("class A {set(v) {};}", {
|
|||||||
end: {line: 1, column: 18}
|
end: {line: 1, column: 18}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 9},
|
start: {line: 1, column: 9},
|
||||||
@ -7106,7 +7106,7 @@ test("class A { static set(v) {};}", {
|
|||||||
end: {line: 1, column: 26}
|
end: {line: 1, column: 26}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 10},
|
start: {line: 1, column: 10},
|
||||||
@ -7207,7 +7207,7 @@ test("class A {*gen(v) { yield v; }}", {
|
|||||||
end: {line: 1, column: 29}
|
end: {line: 1, column: 29}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 9},
|
start: {line: 1, column: 9},
|
||||||
@ -7308,7 +7308,7 @@ test("class A { static *gen(v) { yield v; }}", {
|
|||||||
end: {line: 1, column: 37}
|
end: {line: 1, column: 37}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 10},
|
start: {line: 1, column: 10},
|
||||||
@ -7391,8 +7391,7 @@ test("\"use strict\"; (class A {constructor() { super() }})", {
|
|||||||
expression: {
|
expression: {
|
||||||
type: "CallExpression",
|
type: "CallExpression",
|
||||||
callee: {
|
callee: {
|
||||||
type: "Identifier",
|
type: "SuperExpression",
|
||||||
name: "super",
|
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 40},
|
start: {line: 1, column: 40},
|
||||||
end: {line: 1, column: 45}
|
end: {line: 1, column: 45}
|
||||||
@ -7421,7 +7420,7 @@ test("\"use strict\"; (class A {constructor() { super() }})", {
|
|||||||
end: {line: 1, column: 49}
|
end: {line: 1, column: 49}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "constructor",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 24},
|
start: {line: 1, column: 24},
|
||||||
@ -7454,6 +7453,36 @@ test("\"use strict\"; (class A {constructor() { super() }})", {
|
|||||||
locations: true
|
locations: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("class A {'constructor'() {}}", {
|
||||||
|
type: "Program",
|
||||||
|
body: [{
|
||||||
|
type: "ClassDeclaration",
|
||||||
|
id: {type: "Identifier", name: "A"},
|
||||||
|
superClass: null,
|
||||||
|
body: {
|
||||||
|
type: "ClassBody",
|
||||||
|
body: [{
|
||||||
|
type: "MethodDefinition",
|
||||||
|
computed: false,
|
||||||
|
key: {type: "Literal", value: "constructor"},
|
||||||
|
static: false,
|
||||||
|
kind: "constructor",
|
||||||
|
value: {
|
||||||
|
type: "FunctionExpression",
|
||||||
|
id: null,
|
||||||
|
generator: false,
|
||||||
|
expression: false,
|
||||||
|
params: [],
|
||||||
|
body: {
|
||||||
|
type: "BlockStatement",
|
||||||
|
body: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}, {ecmaVersion: 6});
|
||||||
|
|
||||||
test("class A {static foo() {}}", {
|
test("class A {static foo() {}}", {
|
||||||
type: "Program",
|
type: "Program",
|
||||||
body: [{
|
body: [{
|
||||||
@ -7499,7 +7528,7 @@ test("class A {static foo() {}}", {
|
|||||||
end: {line: 1, column: 24}
|
end: {line: 1, column: 24}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 9},
|
start: {line: 1, column: 9},
|
||||||
@ -7572,7 +7601,7 @@ test("class A {foo() {} static bar() {}}", {
|
|||||||
end: {line: 1, column: 17}
|
end: {line: 1, column: 17}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 9},
|
start: {line: 1, column: 9},
|
||||||
@ -7609,7 +7638,7 @@ test("class A {foo() {} static bar() {}}", {
|
|||||||
end: {line: 1, column: 33}
|
end: {line: 1, column: 33}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 18},
|
start: {line: 1, column: 18},
|
||||||
@ -7693,8 +7722,7 @@ test("\"use strict\"; (class A { static constructor() { super() }})", {
|
|||||||
expression: {
|
expression: {
|
||||||
type: "CallExpression",
|
type: "CallExpression",
|
||||||
callee: {
|
callee: {
|
||||||
type: "Identifier",
|
type: "SuperExpression",
|
||||||
name: "super",
|
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 48},
|
start: {line: 1, column: 48},
|
||||||
end: {line: 1, column: 53}
|
end: {line: 1, column: 53}
|
||||||
@ -7723,7 +7751,7 @@ test("\"use strict\"; (class A { static constructor() { super() }})", {
|
|||||||
end: {line: 1, column: 57}
|
end: {line: 1, column: 57}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: true,
|
static: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 25},
|
start: {line: 1, column: 25},
|
||||||
@ -7802,7 +7830,7 @@ test("class A { foo() {} bar() {}}", {
|
|||||||
end: {line: 1, column: 18}
|
end: {line: 1, column: 18}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 10},
|
start: {line: 1, column: 10},
|
||||||
@ -7839,7 +7867,7 @@ test("class A { foo() {} bar() {}}", {
|
|||||||
end: {line: 1, column: 27}
|
end: {line: 1, column: 27}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 19},
|
start: {line: 1, column: 19},
|
||||||
@ -8450,7 +8478,7 @@ test("class A { static [foo]() {} }", {
|
|||||||
},
|
},
|
||||||
name: "foo"
|
name: "foo"
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
value: {
|
value: {
|
||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
loc: {
|
loc: {
|
||||||
@ -8717,7 +8745,7 @@ test("class A { foo() {} get foo() {} }",{
|
|||||||
},
|
},
|
||||||
name: "foo"
|
name: "foo"
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
value: {
|
value: {
|
||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
loc: {
|
loc: {
|
||||||
@ -9582,7 +9610,7 @@ test("class A {[x]() {}}", {
|
|||||||
},
|
},
|
||||||
name: "x"
|
name: "x"
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
value: {
|
value: {
|
||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
loc: {
|
loc: {
|
||||||
@ -10324,7 +10352,7 @@ test("(class {f({x} = {x: 10}) {}})", {
|
|||||||
end: {line: 1, column: 27}
|
end: {line: 1, column: 27}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
kind: "",
|
kind: "method",
|
||||||
static: false,
|
static: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: {line: 1, column: 8},
|
start: {line: 1, column: 8},
|
||||||
@ -14947,7 +14975,7 @@ test("class A { static() {} }", {
|
|||||||
name: "static"
|
name: "static"
|
||||||
},
|
},
|
||||||
static: false,
|
static: false,
|
||||||
kind: "",
|
kind: "method",
|
||||||
value: {
|
value: {
|
||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
range: [16, 21],
|
range: [16, 21],
|
||||||
@ -15044,7 +15072,7 @@ test("class A { *static() {} }", {
|
|||||||
name: "static"
|
name: "static"
|
||||||
},
|
},
|
||||||
static: false,
|
static: false,
|
||||||
kind: "",
|
kind: "method",
|
||||||
value: {
|
value: {
|
||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
range: [17, 22],
|
range: [17, 22],
|
||||||
3647
vendor/acorn/test/tests-jsx.js
vendored
Normal file
3647
vendor/acorn/test/tests-jsx.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user