Spread attribute support and small optimizations.
Conflicts: acorn.js docs/acorn.html package.json test/tests.js
This commit is contained in:
parent
fe6cafa141
commit
35c8f104bd
@ -1,5 +1,7 @@
|
|||||||
# Acorn (JSX edition)
|
# Acorn (JSX edition)
|
||||||
|
|
||||||
|
[](https://travis-ci.org/RReverser/acorn)
|
||||||
|
|
||||||
This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript.
|
This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript.
|
||||||
|
|
||||||
It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser by integrating pieces
|
It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser by integrating pieces
|
||||||
|
|||||||
292
acorn.js
292
acorn.js
@ -351,6 +351,7 @@
|
|||||||
var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
|
var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
|
||||||
var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
|
var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
|
||||||
var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true};
|
var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true};
|
||||||
|
var _ltSlash = {type: "</"};
|
||||||
|
|
||||||
// Operators. These carry several kinds of properties to help the
|
// Operators. These carry several kinds of properties to help the
|
||||||
// parser use them properly (the presence of these properties is
|
// parser use them properly (the presence of these properties is
|
||||||
@ -385,6 +386,9 @@
|
|||||||
// '*' may be multiply or have special meaning in ES6
|
// '*' may be multiply or have special meaning in ES6
|
||||||
var _star = {binop: 10, beforeExpr: true};
|
var _star = {binop: 10, beforeExpr: true};
|
||||||
|
|
||||||
|
// '<', '>' may be relational or have special meaning in JSX
|
||||||
|
var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true};
|
||||||
|
|
||||||
// Provide access to the token types for external users of the
|
// Provide access to the token types for external users of the
|
||||||
// tokenizer.
|
// tokenizer.
|
||||||
|
|
||||||
@ -544,14 +548,14 @@
|
|||||||
tokEnd = tokPos;
|
tokEnd = tokPos;
|
||||||
if (options.locations) tokEndLoc = new Position;
|
if (options.locations) tokEndLoc = new Position;
|
||||||
tokType = type;
|
tokType = type;
|
||||||
if (shouldSkipSpace !== false && !(inXJSTag && val === '>') && !(inXJSChild && tokType !== _braceL)) {
|
if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
|
||||||
skipSpace();
|
skipSpace();
|
||||||
}
|
}
|
||||||
tokVal = val;
|
tokVal = val;
|
||||||
tokRegexpAllowed = type.beforeExpr;
|
tokRegexpAllowed = type.beforeExpr;
|
||||||
if (options.onToken) {
|
if (options.onToken) {
|
||||||
options.onToken(getCurrentToken());
|
options.onToken(getCurrentToken());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipBlockComment() {
|
function skipBlockComment() {
|
||||||
@ -712,9 +716,16 @@
|
|||||||
skipSpace();
|
skipSpace();
|
||||||
return readToken();
|
return readToken();
|
||||||
}
|
}
|
||||||
if (next === 61)
|
if (next === 61) {
|
||||||
size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
|
size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
|
||||||
return finishOp(_relational, size);
|
return finishOp(_relational, size);
|
||||||
|
}
|
||||||
|
if (next === 47) {
|
||||||
|
// '</', beginning of JSX closing element
|
||||||
|
size = 2;
|
||||||
|
return finishOp(_ltSlash, size);
|
||||||
|
}
|
||||||
|
return finishOp(code === 60 ? _lt : _gt, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readToken_eq_excl(code) { // '=!', '=>'
|
function readToken_eq_excl(code) { // '=!', '=>'
|
||||||
@ -732,34 +743,34 @@
|
|||||||
function getTemplateToken(code) {
|
function getTemplateToken(code) {
|
||||||
// '`' and '${' have special meanings, but they should follow
|
// '`' and '${' have special meanings, but they should follow
|
||||||
// string (can be empty)
|
// string (can be empty)
|
||||||
if (tokType === _string) {
|
if (tokType === _string) {
|
||||||
if (code === 96) { // '`'
|
if (code === 96) { // '`'
|
||||||
++tokPos;
|
++tokPos;
|
||||||
return finishToken(_bquote);
|
return finishToken(_bquote);
|
||||||
} else
|
} else
|
||||||
if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
|
if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
|
||||||
tokPos += 2;
|
tokPos += 2;
|
||||||
return finishToken(_dollarBraceL);
|
return finishToken(_dollarBraceL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (code === 125) { // '}'
|
if (code === 125) { // '}'
|
||||||
++tokPos;
|
++tokPos;
|
||||||
return finishToken(_braceR, undefined, false);
|
return finishToken(_braceR, undefined, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else is considered string literal
|
// anything else is considered string literal
|
||||||
return readTmplString();
|
return readTmplString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTokenFromCode(code) {
|
function getTokenFromCode(code) {
|
||||||
switch (code) {
|
switch(code) {
|
||||||
// The interpretation of a dot depends on whether it is followed
|
// The interpretation of a dot depends on whether it is followed
|
||||||
// by a digit or another two dots.
|
// by a digit or another two dots.
|
||||||
case 46: // '.'
|
case 46: // '.'
|
||||||
return readToken_dot();
|
return readToken_dot();
|
||||||
|
|
||||||
// Punctuation tokens.
|
// Punctuation tokens.
|
||||||
case 40: ++tokPos; return finishToken(_parenL);
|
case 40: ++tokPos; return finishToken(_parenL);
|
||||||
case 41: ++tokPos; return finishToken(_parenR);
|
case 41: ++tokPos; return finishToken(_parenR);
|
||||||
case 59: ++tokPos; return finishToken(_semi);
|
case 59: ++tokPos; return finishToken(_semi);
|
||||||
@ -784,12 +795,12 @@
|
|||||||
if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number
|
if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number
|
||||||
if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number
|
if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number
|
||||||
}
|
}
|
||||||
// Anything else beginning with a digit is an integer, octal
|
// Anything else beginning with a digit is an integer, octal
|
||||||
// number, or float.
|
// number, or float.
|
||||||
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
|
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
|
||||||
return readNumber(false);
|
return readNumber(false);
|
||||||
|
|
||||||
// Quotes produce strings.
|
// Quotes produce strings.
|
||||||
case 34: case 39: // '"', "'"
|
case 34: case 39: // '"', "'"
|
||||||
return inXJSTag ? readXJSStringLiteral() : readString(code);
|
return inXJSTag ? readXJSStringLiteral() : readString(code);
|
||||||
|
|
||||||
@ -957,7 +968,7 @@
|
|||||||
|
|
||||||
function readCodePoint() {
|
function readCodePoint() {
|
||||||
var ch = input.charCodeAt(tokPos), code;
|
var ch = input.charCodeAt(tokPos), code;
|
||||||
|
|
||||||
if (ch === 123) {
|
if (ch === 123) {
|
||||||
if (options.ecmaVersion < 6) unexpected();
|
if (options.ecmaVersion < 6) unexpected();
|
||||||
++tokPos;
|
++tokPos;
|
||||||
@ -993,9 +1004,9 @@
|
|||||||
++tokPos;
|
++tokPos;
|
||||||
if (newline.test(String.fromCharCode(ch))) {
|
if (newline.test(String.fromCharCode(ch))) {
|
||||||
raise(tokStart, "Unterminated string constant");
|
raise(tokStart, "Unterminated string constant");
|
||||||
}
|
}
|
||||||
out += String.fromCharCode(ch); // '\'
|
out += String.fromCharCode(ch); // '\'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,15 +1022,15 @@
|
|||||||
} else {
|
} else {
|
||||||
++tokPos;
|
++tokPos;
|
||||||
if (newline.test(String.fromCharCode(ch))) {
|
if (newline.test(String.fromCharCode(ch))) {
|
||||||
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
|
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
|
||||||
++tokPos;
|
++tokPos;
|
||||||
ch = 10;
|
ch = 10;
|
||||||
}
|
}
|
||||||
if (options.locations) {
|
if (options.locations) {
|
||||||
++tokCurLine;
|
++tokCurLine;
|
||||||
tokLineStart = tokPos;
|
tokLineStart = tokPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out += String.fromCharCode(ch); // '\'
|
out += String.fromCharCode(ch); // '\'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1497,7 +1508,7 @@
|
|||||||
this.start = tokStart;
|
this.start = tokStart;
|
||||||
this.end = null;
|
this.end = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Node = Node;
|
exports.Node = Node;
|
||||||
|
|
||||||
function SourceLocation() {
|
function SourceLocation() {
|
||||||
@ -1611,7 +1622,7 @@
|
|||||||
function has(obj, propName) {
|
function has(obj, propName) {
|
||||||
return Object.prototype.hasOwnProperty.call(obj, propName);
|
return Object.prototype.hasOwnProperty.call(obj, propName);
|
||||||
}
|
}
|
||||||
// Convert existing expression atom to assignable pattern
|
// Convert existing expression atom to assignable pattern
|
||||||
// if possible.
|
// if possible.
|
||||||
|
|
||||||
function toAssignable(node, allowSpread, checkType) {
|
function toAssignable(node, allowSpread, checkType) {
|
||||||
@ -1619,7 +1630,7 @@
|
|||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case "Identifier":
|
case "Identifier":
|
||||||
case "MemberExpression":
|
case "MemberExpression":
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ObjectExpression":
|
case "ObjectExpression":
|
||||||
node.type = "ObjectPattern";
|
node.type = "ObjectPattern";
|
||||||
@ -1726,7 +1737,7 @@
|
|||||||
: "Assigning to " + expr.name + " in strict mode"
|
: "Assigning to " + expr.name + " in strict mode"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "MemberExpression":
|
case "MemberExpression":
|
||||||
if (!isBinding) break;
|
if (!isBinding) break;
|
||||||
|
|
||||||
@ -1746,8 +1757,8 @@
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
raise(expr.start, "Assigning to rvalue");
|
raise(expr.start, "Assigning to rvalue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ### Statement parsing
|
// ### Statement parsing
|
||||||
@ -1826,7 +1837,7 @@
|
|||||||
else return parseExpressionStatement(node, expr);
|
else return parseExpressionStatement(node, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseBreakContinueStatement(node, keyword) {
|
function parseBreakContinueStatement(node, keyword) {
|
||||||
var isBreak = keyword == "break";
|
var isBreak = keyword == "break";
|
||||||
next();
|
next();
|
||||||
@ -1849,13 +1860,13 @@
|
|||||||
if (i === labels.length) raise(node.start, "Unsyntactic " + keyword);
|
if (i === labels.length) raise(node.start, "Unsyntactic " + keyword);
|
||||||
return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
|
return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDebuggerStatement(node) {
|
function parseDebuggerStatement(node) {
|
||||||
next();
|
next();
|
||||||
semicolon();
|
semicolon();
|
||||||
return finishNode(node, "DebuggerStatement");
|
return finishNode(node, "DebuggerStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDoStatement(node) {
|
function parseDoStatement(node) {
|
||||||
next();
|
next();
|
||||||
labels.push(loopLabel);
|
labels.push(loopLabel);
|
||||||
@ -1866,7 +1877,7 @@
|
|||||||
semicolon();
|
semicolon();
|
||||||
return finishNode(node, "DoWhileStatement");
|
return finishNode(node, "DoWhileStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
|
// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
|
||||||
// loop is non-trivial. Basically, we have to parse the init `var`
|
// loop is non-trivial. Basically, we have to parse the init `var`
|
||||||
// statement or expression, disallowing the `in` operator (see
|
// statement or expression, disallowing the `in` operator (see
|
||||||
@ -1874,7 +1885,7 @@
|
|||||||
// whether the next token is `in` or `of`. When there is no init
|
// whether the next token is `in` or `of`. When there is no init
|
||||||
// part (semicolon immediately after the opening parenthesis), it
|
// part (semicolon immediately after the opening parenthesis), it
|
||||||
// is a regular `for` loop.
|
// is a regular `for` loop.
|
||||||
|
|
||||||
function parseForStatement(node) {
|
function parseForStatement(node) {
|
||||||
next();
|
next();
|
||||||
labels.push(loopLabel);
|
labels.push(loopLabel);
|
||||||
@ -1897,12 +1908,12 @@
|
|||||||
}
|
}
|
||||||
return parseFor(node, init);
|
return parseFor(node, init);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFunctionStatement(node) {
|
function parseFunctionStatement(node) {
|
||||||
next();
|
next();
|
||||||
return parseFunction(node, true);
|
return parseFunction(node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseIfStatement(node) {
|
function parseIfStatement(node) {
|
||||||
next();
|
next();
|
||||||
node.test = parseParenExpression();
|
node.test = parseParenExpression();
|
||||||
@ -1910,7 +1921,7 @@
|
|||||||
node.alternate = eat(_else) ? parseStatement() : null;
|
node.alternate = eat(_else) ? parseStatement() : null;
|
||||||
return finishNode(node, "IfStatement");
|
return finishNode(node, "IfStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseReturnStatement(node) {
|
function parseReturnStatement(node) {
|
||||||
if (!inFunction && !options.allowReturnOutsideFunction)
|
if (!inFunction && !options.allowReturnOutsideFunction)
|
||||||
raise(tokStart, "'return' outside of function");
|
raise(tokStart, "'return' outside of function");
|
||||||
@ -1924,7 +1935,7 @@
|
|||||||
else { node.argument = parseExpression(); semicolon(); }
|
else { node.argument = parseExpression(); semicolon(); }
|
||||||
return finishNode(node, "ReturnStatement");
|
return finishNode(node, "ReturnStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSwitchStatement(node) {
|
function parseSwitchStatement(node) {
|
||||||
next();
|
next();
|
||||||
node.discriminant = parseParenExpression();
|
node.discriminant = parseParenExpression();
|
||||||
@ -1959,7 +1970,7 @@
|
|||||||
labels.pop();
|
labels.pop();
|
||||||
return finishNode(node, "SwitchStatement");
|
return finishNode(node, "SwitchStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseThrowStatement(node) {
|
function parseThrowStatement(node) {
|
||||||
next();
|
next();
|
||||||
if (newline.test(input.slice(lastEnd, tokStart)))
|
if (newline.test(input.slice(lastEnd, tokStart)))
|
||||||
@ -1968,7 +1979,7 @@
|
|||||||
semicolon();
|
semicolon();
|
||||||
return finishNode(node, "ThrowStatement");
|
return finishNode(node, "ThrowStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTryStatement(node) {
|
function parseTryStatement(node) {
|
||||||
next();
|
next();
|
||||||
node.block = parseBlock();
|
node.block = parseBlock();
|
||||||
@ -1991,14 +2002,14 @@
|
|||||||
raise(node.start, "Missing catch or finally clause");
|
raise(node.start, "Missing catch or finally clause");
|
||||||
return finishNode(node, "TryStatement");
|
return finishNode(node, "TryStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseVarStatement(node, kind) {
|
function parseVarStatement(node, kind) {
|
||||||
next();
|
next();
|
||||||
parseVar(node, false, kind);
|
parseVar(node, false, kind);
|
||||||
semicolon();
|
semicolon();
|
||||||
return finishNode(node, "VariableDeclaration");
|
return finishNode(node, "VariableDeclaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseWhileStatement(node) {
|
function parseWhileStatement(node) {
|
||||||
next();
|
next();
|
||||||
node.test = parseParenExpression();
|
node.test = parseParenExpression();
|
||||||
@ -2007,7 +2018,7 @@
|
|||||||
labels.pop();
|
labels.pop();
|
||||||
return finishNode(node, "WhileStatement");
|
return finishNode(node, "WhileStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseWithStatement(node) {
|
function parseWithStatement(node) {
|
||||||
if (strict) raise(tokStart, "'with' in strict mode");
|
if (strict) raise(tokStart, "'with' in strict mode");
|
||||||
next();
|
next();
|
||||||
@ -2015,12 +2026,12 @@
|
|||||||
node.body = parseStatement();
|
node.body = parseStatement();
|
||||||
return finishNode(node, "WithStatement");
|
return finishNode(node, "WithStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEmptyStatement(node) {
|
function parseEmptyStatement(node) {
|
||||||
next();
|
next();
|
||||||
return finishNode(node, "EmptyStatement");
|
return finishNode(node, "EmptyStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseLabeledStatement(node, maybeName, expr) {
|
function parseLabeledStatement(node, maybeName, expr) {
|
||||||
for (var i = 0; i < labels.length; ++i)
|
for (var i = 0; i < labels.length; ++i)
|
||||||
if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
|
if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
|
||||||
@ -2031,7 +2042,7 @@
|
|||||||
node.label = expr;
|
node.label = expr;
|
||||||
return finishNode(node, "LabeledStatement");
|
return finishNode(node, "LabeledStatement");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseExpressionStatement(node, expr) {
|
function parseExpressionStatement(node, expr) {
|
||||||
node.expression = expr;
|
node.expression = expr;
|
||||||
semicolon();
|
semicolon();
|
||||||
@ -2272,7 +2283,7 @@
|
|||||||
var node = startNode();
|
var node = startNode();
|
||||||
next();
|
next();
|
||||||
return finishNode(node, "ThisExpression");
|
return finishNode(node, "ThisExpression");
|
||||||
|
|
||||||
case _yield:
|
case _yield:
|
||||||
if (inGenerator) return parseYield();
|
if (inGenerator) return parseYield();
|
||||||
|
|
||||||
@ -2282,7 +2293,7 @@
|
|||||||
return parseArrowExpression(startNodeFrom(id), [id]);
|
return parseArrowExpression(startNodeFrom(id), [id]);
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
case _num: case _string: case _regexp: case _xjsText:
|
case _num: case _string: case _regexp: case _xjsText:
|
||||||
var node = startNode();
|
var node = startNode();
|
||||||
node.value = tokVal;
|
node.value = tokVal;
|
||||||
@ -2304,28 +2315,28 @@
|
|||||||
if (options.ecmaVersion >= 6 && tokType === _for) {
|
if (options.ecmaVersion >= 6 && tokType === _for) {
|
||||||
val = parseComprehension(startNode(), true);
|
val = parseComprehension(startNode(), true);
|
||||||
} else {
|
} else {
|
||||||
var oldParenL = ++metParenL;
|
var oldParenL = ++metParenL;
|
||||||
if (tokType !== _parenR) {
|
if (tokType !== _parenR) {
|
||||||
val = parseExpression();
|
val = parseExpression();
|
||||||
exprList = val.type === "SequenceExpression" ? val.expressions : [val];
|
exprList = val.type === "SequenceExpression" ? val.expressions : [val];
|
||||||
} else {
|
} else {
|
||||||
exprList = [];
|
exprList = [];
|
||||||
}
|
}
|
||||||
expect(_parenR);
|
expect(_parenR);
|
||||||
// if '=>' follows '(...)', convert contents to arguments
|
// if '=>' follows '(...)', convert contents to arguments
|
||||||
if (metParenL === oldParenL && eat(_arrow)) {
|
if (metParenL === oldParenL && eat(_arrow)) {
|
||||||
val = parseArrowExpression(startNode(), exprList);
|
val = parseArrowExpression(startNode(), exprList);
|
||||||
} else {
|
} else {
|
||||||
// forbid '()' before everything but '=>'
|
// forbid '()' before everything but '=>'
|
||||||
if (!val) unexpected(lastStart);
|
if (!val) unexpected(lastStart);
|
||||||
// forbid '...' in sequence expressions
|
// forbid '...' in sequence expressions
|
||||||
if (options.ecmaVersion >= 6) {
|
if (options.ecmaVersion >= 6) {
|
||||||
for (var i = 0; i < exprList.length; i++) {
|
for (var i = 0; i < exprList.length; i++) {
|
||||||
if (exprList[i].type === "SpreadElement") unexpected();
|
if (exprList[i].type === "SpreadElement") unexpected();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
val.start = tokStart1;
|
val.start = tokStart1;
|
||||||
val.end = lastEnd;
|
val.end = lastEnd;
|
||||||
if (options.locations) {
|
if (options.locations) {
|
||||||
@ -2343,7 +2354,7 @@
|
|||||||
// check whether this is array comprehension or regular array
|
// check whether this is array comprehension or regular array
|
||||||
if (options.ecmaVersion >= 6 && tokType === _for) {
|
if (options.ecmaVersion >= 6 && tokType === _for) {
|
||||||
return parseComprehension(node, false);
|
return parseComprehension(node, false);
|
||||||
}
|
}
|
||||||
node.elements = parseExprList(_bracketR, true, true);
|
node.elements = parseExprList(_bracketR, true, true);
|
||||||
return finishNode(node, "ArrayExpression");
|
return finishNode(node, "ArrayExpression");
|
||||||
|
|
||||||
@ -2367,10 +2378,8 @@
|
|||||||
case _bquote:
|
case _bquote:
|
||||||
return parseTemplate();
|
return parseTemplate();
|
||||||
|
|
||||||
case _relational:
|
case _lt:
|
||||||
if (tokVal === '<') {
|
return parseXJSElement();
|
||||||
return parseXJSElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
@ -2467,9 +2476,9 @@
|
|||||||
|
|
||||||
checkPropClash(prop, propHash);
|
checkPropClash(prop, propHash);
|
||||||
node.properties.push(finishNode(prop, "Property"));
|
node.properties.push(finishNode(prop, "Property"));
|
||||||
}
|
}
|
||||||
return finishNode(node, "ObjectExpression");
|
return finishNode(node, "ObjectExpression");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePropertyName(prop) {
|
function parsePropertyName(prop) {
|
||||||
if (options.ecmaVersion >= 6) {
|
if (options.ecmaVersion >= 6) {
|
||||||
@ -2494,7 +2503,7 @@
|
|||||||
node.defaults = [];
|
node.defaults = [];
|
||||||
node.rest = null;
|
node.rest = null;
|
||||||
node.generator = false;
|
node.generator = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a function declaration or literal (depending on the
|
// Parse a function declaration or literal (depending on the
|
||||||
@ -2536,7 +2545,7 @@
|
|||||||
initFunction(node);
|
initFunction(node);
|
||||||
|
|
||||||
var defaults = node.defaults, hasDefaults = false;
|
var defaults = node.defaults, hasDefaults = false;
|
||||||
|
|
||||||
for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
|
for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
|
||||||
var param = params[i];
|
var param = params[i];
|
||||||
|
|
||||||
@ -2566,7 +2575,7 @@
|
|||||||
|
|
||||||
function parseFunctionParams(node) {
|
function parseFunctionParams(node) {
|
||||||
var defaults = [], hasDefaults = false;
|
var defaults = [], hasDefaults = false;
|
||||||
|
|
||||||
expect(_parenL);
|
expect(_parenL);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (eat(_parenR)) {
|
if (eat(_parenR)) {
|
||||||
@ -2597,16 +2606,16 @@
|
|||||||
|
|
||||||
function parseFunctionBody(node, allowExpression) {
|
function parseFunctionBody(node, allowExpression) {
|
||||||
var isExpression = allowExpression && tokType !== _braceL;
|
var isExpression = allowExpression && tokType !== _braceL;
|
||||||
|
|
||||||
if (isExpression) {
|
if (isExpression) {
|
||||||
node.body = parseExpression(true);
|
node.body = parseExpression(true);
|
||||||
node.expression = true;
|
node.expression = true;
|
||||||
} else {
|
} else {
|
||||||
// Start a new scope with regard to labels and the `inFunction`
|
// Start a new scope with regard to labels and the `inFunction`
|
||||||
// flag (restore them to their old value afterwards).
|
// flag (restore them to their old value afterwards).
|
||||||
var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
|
var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
|
||||||
inFunction = true; inGenerator = node.generator; labels = [];
|
inFunction = true; inGenerator = node.generator; labels = [];
|
||||||
node.body = parseBlock(true);
|
node.body = parseBlock(true);
|
||||||
node.expression = false;
|
node.expression = false;
|
||||||
inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels;
|
inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels;
|
||||||
}
|
}
|
||||||
@ -2627,7 +2636,7 @@
|
|||||||
|
|
||||||
// Parse a class declaration or literal (depending on the
|
// Parse a class declaration or literal (depending on the
|
||||||
// `isStatement` parameter).
|
// `isStatement` parameter).
|
||||||
|
|
||||||
function parseClass(node, isStatement) {
|
function parseClass(node, isStatement) {
|
||||||
next();
|
next();
|
||||||
node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
|
node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
|
||||||
@ -2640,9 +2649,9 @@
|
|||||||
if (tokType === _name && tokVal === "static") {
|
if (tokType === _name && tokVal === "static") {
|
||||||
next();
|
next();
|
||||||
method['static'] = true;
|
method['static'] = true;
|
||||||
} else {
|
} else {
|
||||||
method['static'] = false;
|
method['static'] = false;
|
||||||
}
|
}
|
||||||
var isGenerator = eat(_star);
|
var isGenerator = eat(_star);
|
||||||
parsePropertyName(method);
|
parsePropertyName(method);
|
||||||
if (tokType === _name && !method.computed && method.key.type === "Identifier" &&
|
if (tokType === _name && !method.computed && method.key.type === "Identifier" &&
|
||||||
@ -2851,8 +2860,8 @@
|
|||||||
node.delegate = false;
|
node.delegate = false;
|
||||||
node.argument = null;
|
node.argument = null;
|
||||||
} else {
|
} else {
|
||||||
node.delegate = eat(_star);
|
node.delegate = eat(_star);
|
||||||
node.argument = parseExpression(true);
|
node.argument = parseExpression(true);
|
||||||
}
|
}
|
||||||
return finishNode(node, "YieldExpression");
|
return finishNode(node, "YieldExpression");
|
||||||
}
|
}
|
||||||
@ -2972,24 +2981,27 @@
|
|||||||
// Parses any type of JSX attribute value.
|
// Parses any type of JSX attribute value.
|
||||||
|
|
||||||
function parseXJSAttributeValue() {
|
function parseXJSAttributeValue() {
|
||||||
var node;
|
switch (tokType) {
|
||||||
if (tokType === _braceL) {
|
case _braceL:
|
||||||
node = parseXJSExpressionContainer();
|
var node = parseXJSExpressionContainer();
|
||||||
if (node.expression.type === "XJSEmptyExpression") {
|
if (node.expression.type === "XJSEmptyExpression") {
|
||||||
raise(
|
raise(
|
||||||
node.start,
|
node.start,
|
||||||
'XJS attributes must only be assigned a non-empty ' +
|
'XJS attributes must only be assigned a non-empty ' +
|
||||||
'expression'
|
'expression'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (tokVal === '<') {
|
return node;
|
||||||
node = parseXJSElement();
|
|
||||||
} else if (tokType === _xjsText) {
|
case _lt:
|
||||||
node = parseExprAtom();
|
return parseXJSElement();
|
||||||
} else {
|
|
||||||
raise(tokStart, "XJS value should be either an expression or a quoted XJS text");
|
case _xjsText:
|
||||||
|
return parseExprAtom();
|
||||||
|
|
||||||
|
default:
|
||||||
|
raise(tokStart, "XJS value should be either an expression or a quoted XJS text");
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XJSEmptyExpression is unique type since it doesn't actually parse anything,
|
// XJSEmptyExpression is unique type since it doesn't actually parse anything,
|
||||||
@ -3022,28 +3034,54 @@
|
|||||||
var origInXJSTag = inXJSTag;
|
var origInXJSTag = inXJSTag;
|
||||||
inXJSTag = false;
|
inXJSTag = false;
|
||||||
|
|
||||||
expect(_braceL);
|
next();
|
||||||
|
|
||||||
node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
|
node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
|
||||||
|
|
||||||
inXJSTag = origInXJSTag;
|
inXJSTag = origInXJSTag;
|
||||||
|
|
||||||
expect(_braceR);
|
expect(_braceR);
|
||||||
|
|
||||||
return finishNode(node, "XJSExpressionContainer");
|
return finishNode(node, "XJSExpressionContainer");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses following JSX attribute name-value pair.
|
// Parses following JSX attribute name-value pair.
|
||||||
|
|
||||||
function parseXJSAttribute() {
|
function parseXJSAttribute() {
|
||||||
var node = startNode();
|
if (tokType === _braceL) {
|
||||||
|
var tokStart1 = tokStart, tokStartLoc1 = tokStartLoc;
|
||||||
|
|
||||||
|
var origInXJSTag = inXJSTag;
|
||||||
|
inXJSTag = false;
|
||||||
|
|
||||||
|
next();
|
||||||
|
var node = parseSpread();
|
||||||
|
|
||||||
|
inXJSTag = origInXJSTag;
|
||||||
|
|
||||||
|
expect(_braceR);
|
||||||
|
node.type = "XJSSpreadAttribute";
|
||||||
|
|
||||||
|
node.start = tokStart1;
|
||||||
|
node.end = lastEnd;
|
||||||
|
if (options.locations) {
|
||||||
|
node.loc.start = tokStartLoc1;
|
||||||
|
node.loc.end = lastEndLoc;
|
||||||
|
}
|
||||||
|
if (options.ranges) {
|
||||||
|
node.range = [tokStart1, lastEnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = startNode();
|
||||||
node.name = parseXJSAttributeName();
|
node.name = parseXJSAttributeName();
|
||||||
|
|
||||||
// HTML empty attribute
|
// HTML empty attribute
|
||||||
if (tokVal === "=") {
|
if (tokType === _eq) {
|
||||||
next();
|
next();
|
||||||
node.value = parseXJSAttributeValue();
|
node.value = parseXJSAttributeValue();
|
||||||
|
} else {
|
||||||
|
node.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return finishNode(node, "XJSAttribute");
|
return finishNode(node, "XJSAttribute");
|
||||||
@ -3074,11 +3112,11 @@
|
|||||||
inXJSChild = false;
|
inXJSChild = false;
|
||||||
inXJSTag = true;
|
inXJSTag = true;
|
||||||
|
|
||||||
expectChar('<');
|
next();
|
||||||
|
|
||||||
node.name = parseXJSElementName();
|
node.name = parseXJSElementName();
|
||||||
|
|
||||||
while (tokType !== _eof && tokType !== _slash && tokVal !== '>') {
|
while (tokType !== _eof && tokType !== _slash && tokType !== _gt) {
|
||||||
attributes.push(parseXJSAttribute());
|
attributes.push(parseXJSAttribute());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3091,7 +3129,7 @@
|
|||||||
inXJSChild = true;
|
inXJSChild = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
expectChar('>');
|
expect(_gt);
|
||||||
|
|
||||||
return finishNode(node, "XJSOpeningElement");
|
return finishNode(node, "XJSOpeningElement");
|
||||||
}
|
}
|
||||||
@ -3105,8 +3143,7 @@
|
|||||||
inXJSChild = false;
|
inXJSChild = false;
|
||||||
inXJSTag = true;
|
inXJSTag = true;
|
||||||
tokRegexpAllowed = false;
|
tokRegexpAllowed = false;
|
||||||
expectChar('<');
|
expect(_ltSlash);
|
||||||
expect(_slash);
|
|
||||||
node.name = parseXJSElementName();
|
node.name = parseXJSElementName();
|
||||||
skipSpace();
|
skipSpace();
|
||||||
// A valid token is expected after >, so parser needs to know
|
// A valid token is expected after >, so parser needs to know
|
||||||
@ -3114,7 +3151,7 @@
|
|||||||
inXJSChild = origInXJSChild;
|
inXJSChild = origInXJSChild;
|
||||||
inXJSTag = origInXJSTag;
|
inXJSTag = origInXJSTag;
|
||||||
tokRegexpAllowed = false;
|
tokRegexpAllowed = false;
|
||||||
expectChar('>');
|
expect(_gt);
|
||||||
return finishNode(node, "XJSClosingElement");
|
return finishNode(node, "XJSClosingElement");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3127,14 +3164,15 @@
|
|||||||
|
|
||||||
var origInXJSChild = inXJSChild;
|
var origInXJSChild = inXJSChild;
|
||||||
var openingElement = parseXJSOpeningElement();
|
var openingElement = parseXJSOpeningElement();
|
||||||
|
var closingElement = null;
|
||||||
|
|
||||||
if (!openingElement.selfClosing) {
|
if (!openingElement.selfClosing) {
|
||||||
while (tokType !== _eof && !(tokVal === '<' && nextChar() === '/')) {
|
while (tokType !== _eof && tokType !== _ltSlash) {
|
||||||
inXJSChild = true;
|
inXJSChild = true;
|
||||||
children.push(parseXJSChild());
|
children.push(parseXJSChild());
|
||||||
}
|
}
|
||||||
inXJSChild = origInXJSChild;
|
inXJSChild = origInXJSChild;
|
||||||
var closingElement = parseXJSClosingElement();
|
closingElement = parseXJSClosingElement();
|
||||||
if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) {
|
if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) {
|
||||||
raise(
|
raise(
|
||||||
closingElement.start,
|
closingElement.start,
|
||||||
@ -3152,7 +3190,7 @@
|
|||||||
// element, we disallow it here in the parser in order to provide a
|
// element, we disallow it here in the parser in order to provide a
|
||||||
// better error message. (In the rare case that the less-than operator
|
// better error message. (In the rare case that the less-than operator
|
||||||
// was intended, the left tag can be wrapped in parentheses.)
|
// was intended, the left tag can be wrapped in parentheses.)
|
||||||
if (!origInXJSChild && tokVal === '<') {
|
if (!origInXJSChild && tokType === _lt) {
|
||||||
raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag");
|
raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2038
docs/acorn.html
2038
docs/acorn.html
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
"name": "acorn-jsx",
|
"name": "acorn-jsx",
|
||||||
"description": "Alternative React JSX parser",
|
"description": "Alternative React JSX parser",
|
||||||
"main": "acorn.js",
|
"main": "acorn.js",
|
||||||
"version": "0.7.1",
|
"version": "0.7.1-1",
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
{
|
{
|
||||||
"name": "Marijn Haverbeke",
|
"name": "Marijn Haverbeke",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
var driver = require("./driver.js");
|
var driver = require("./driver.js");
|
||||||
require("./tests.js");
|
require("./tests.js");
|
||||||
require("./tests-harmony.js");
|
require("./tests-harmony.js");
|
||||||
|
require("./tests-jsx.js");
|
||||||
|
|
||||||
var testsRun = 0, failed = 0;
|
var testsRun = 0, failed = 0;
|
||||||
function report(state, code, message) {
|
function report(state, code, message) {
|
||||||
|
|||||||
3801
test/tests-jsx.js
3801
test/tests-jsx.js
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,6 @@ if (typeof exports != "undefined") {
|
|||||||
var testFail = require("./driver.js").testFail;
|
var testFail = require("./driver.js").testFail;
|
||||||
var testAssert = require("./driver.js").testAssert;
|
var testAssert = require("./driver.js").testAssert;
|
||||||
var acorn = require("..");
|
var acorn = require("..");
|
||||||
require("./tests-jsx.js");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("this\n", {
|
test("this\n", {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user