Merge branch 'master' into harmony-2.8.0
This commit is contained in:
107
lib/parse.js
107
lib/parse.js
@@ -239,12 +239,11 @@ function JS_Parse_Error(message, filename, line, col, pos) {
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
this.pos = pos;
|
||||
this.stack = new Error().stack;
|
||||
};
|
||||
|
||||
JS_Parse_Error.prototype.toString = function() {
|
||||
return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
|
||||
};
|
||||
JS_Parse_Error.prototype = Object.create(Error.prototype);
|
||||
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
|
||||
JS_Parse_Error.prototype.name = "SyntaxError";
|
||||
configure_error_stack(JS_Parse_Error);
|
||||
|
||||
function js_error(message, filename, line, col, pos) {
|
||||
throw new JS_Parse_Error(message, filename, line, col, pos);
|
||||
@@ -404,13 +403,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
});
|
||||
if (prefix) num = prefix + num;
|
||||
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
||||
parse_error("SyntaxError: Legacy octal literals are not allowed in strict mode");
|
||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||
}
|
||||
var valid = parse_js_number(num);
|
||||
if (!isNaN(valid)) {
|
||||
return token("num", valid);
|
||||
} else {
|
||||
parse_error("SyntaxError: Invalid syntax: " + num);
|
||||
parse_error("Invalid syntax: " + num);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -428,13 +427,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (peek() == "{") {
|
||||
next(true);
|
||||
if (peek() === "}")
|
||||
parse_error("SyntaxError: Expecting hex-character between {}");
|
||||
parse_error("Expecting hex-character between {}");
|
||||
while (peek() == "0") next(true); // No significance
|
||||
var result, length = find("}", true) - S.pos;
|
||||
// Avoid 32 bit integer overflow (1 << 32 === 1)
|
||||
// We know first character isn't 0 and thus out of range anyway
|
||||
if (length > 6 || (result = hex_bytes(length)) > 0x10FFFF) {
|
||||
parse_error("SyntaxError: Unicode reference out of bounce");
|
||||
parse_error("Unicode reference out of bounce");
|
||||
}
|
||||
next(true);
|
||||
return from_char_code(result);
|
||||
@@ -464,7 +463,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
// Parse
|
||||
if (ch === "0") return "\0";
|
||||
if (ch.length > 0 && next_token.has_directive("use strict"))
|
||||
parse_error("SyntaxError: Legacy octal escape sequences are not allowed in strict mode");
|
||||
parse_error("Legacy octal escape sequences are not allowed in strict mode");
|
||||
return String.fromCharCode(parseInt(ch, 8));
|
||||
}
|
||||
|
||||
@@ -473,18 +472,18 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
for (; n > 0; --n) {
|
||||
var digit = parseInt(next(true), 16);
|
||||
if (isNaN(digit))
|
||||
parse_error("SyntaxError: Invalid hex-character pattern in string");
|
||||
parse_error("Invalid hex-character pattern in string");
|
||||
num = (num << 4) | digit;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
|
||||
var read_string = with_eof_error("SyntaxError: Unterminated string constant", function(quote_char){
|
||||
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
||||
var quote = next(), ret = "";
|
||||
for (;;) {
|
||||
var ch = next(true, true);
|
||||
if (ch == "\\") ch = read_escaped_char(true);
|
||||
else if (NEWLINE_CHARS(ch)) parse_error("SyntaxError: Unterminated string constant");
|
||||
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
|
||||
else if (ch == quote) break;
|
||||
ret += ch;
|
||||
}
|
||||
@@ -493,7 +492,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return tok;
|
||||
});
|
||||
|
||||
var read_template_characters = with_eof_error("SyntaxError: Unterminated template", function(begin){
|
||||
var read_template_characters = with_eof_error("Unterminated template", function(begin){
|
||||
if (begin) {
|
||||
S.template_braces.push(S.brace_counter);
|
||||
}
|
||||
@@ -543,7 +542,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return next_token;
|
||||
};
|
||||
|
||||
var skip_multiline_comment = with_eof_error("SyntaxError: Unterminated multiline comment", function(){
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("*/", true);
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
||||
@@ -555,13 +554,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return next_token;
|
||||
});
|
||||
|
||||
var read_name = with_eof_error("SyntaxError: Unterminated identifier name", function() {
|
||||
var read_name = with_eof_error("Unterminated identifier name", function() {
|
||||
var name = "", ch, escaped = false, hex;
|
||||
var read_escaped_identifier_char = function() {
|
||||
escaped = true;
|
||||
next();
|
||||
if (peek() !== "u") {
|
||||
parse_error("SyntaxError: Expecting UnicodeEscapeSequence -- uXXXX or u{XXXX}");
|
||||
parse_error("Expecting UnicodeEscapeSequence -- uXXXX or u{XXXX}");
|
||||
}
|
||||
return read_escaped_char();
|
||||
}
|
||||
@@ -570,7 +569,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if ((name = peek()) === "\\") {
|
||||
name = read_escaped_identifier_char();
|
||||
if (!is_identifier_start(name)) {
|
||||
parse_error("SyntaxError: First identifier char is an invalid identifier char");
|
||||
parse_error("First identifier char is an invalid identifier char");
|
||||
}
|
||||
} else if (is_identifier_start(name)){
|
||||
next();
|
||||
@@ -583,7 +582,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if ((ch = peek()) === "\\") {
|
||||
ch = read_escaped_identifier_char();
|
||||
if (!is_identifier_char(ch)) {
|
||||
parse_error("SyntaxError: Invalid escaped identifier char");
|
||||
parse_error("Invalid escaped identifier char");
|
||||
}
|
||||
} else {
|
||||
if (!is_identifier_char(ch)) {
|
||||
@@ -594,15 +593,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
name += ch;
|
||||
}
|
||||
if (RESERVED_WORDS(name) && escaped) {
|
||||
parse_error("SyntaxError: Escaped characters are not allowed in keywords");
|
||||
parse_error("Escaped characters are not allowed in keywords");
|
||||
}
|
||||
return name;
|
||||
});
|
||||
|
||||
var read_regexp = with_eof_error("SyntaxError: Unterminated regular expression", function(regexp){
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
|
||||
var prev_backslash = false, ch, in_class = false;
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
parse_error("SyntaxError: Unexpected line terminator");
|
||||
parse_error("Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
regexp += "\\" + ch;
|
||||
prev_backslash = false;
|
||||
@@ -623,7 +622,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
try {
|
||||
return token("regexp", new RegExp(regexp, mods));
|
||||
} catch(e) {
|
||||
parse_error("SyntaxError: " + e.message);
|
||||
parse_error(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -752,7 +751,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
parse_error("SyntaxError: Unexpected character '" + ch + "'");
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
};
|
||||
|
||||
next_token.next = next;
|
||||
@@ -914,14 +913,14 @@ function parse($TEXT, options) {
|
||||
function unexpected(token) {
|
||||
if (token == null)
|
||||
token = S.token;
|
||||
token_error(token, "SyntaxError: Unexpected token: " + token.type + " (" + token.value + ")");
|
||||
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
|
||||
};
|
||||
|
||||
function expect_token(type, val) {
|
||||
if (is(type, val)) {
|
||||
return next();
|
||||
}
|
||||
token_error(S.token, "SyntaxError: Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
||||
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
||||
};
|
||||
|
||||
function expect(punc) { return expect_token("punc", punc); };
|
||||
@@ -1058,7 +1057,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "return":
|
||||
if (S.in_function == 0 && !options.bare_returns)
|
||||
croak("SyntaxError: 'return' outside of function");
|
||||
croak("'return' outside of function");
|
||||
return new AST_Return({
|
||||
value: ( is("punc", ";")
|
||||
? (next(), null)
|
||||
@@ -1075,7 +1074,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "throw":
|
||||
if (S.token.nlb)
|
||||
croak("SyntaxError: Illegal newline after 'throw'");
|
||||
croak("Illegal newline after 'throw'");
|
||||
return new AST_Throw({
|
||||
value: (tmp = expression(true), semicolon(), tmp)
|
||||
});
|
||||
@@ -1094,7 +1093,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "with":
|
||||
if (S.input.has_directive("use strict")) {
|
||||
croak("SyntaxError: Strict mode may not include a with statement");
|
||||
croak("Strict mode may not include a with statement");
|
||||
}
|
||||
return new AST_With({
|
||||
expression : parenthesised(),
|
||||
@@ -1115,14 +1114,14 @@ function parse($TEXT, options) {
|
||||
var label = as_symbol(AST_Label);
|
||||
if (label.name === "yield" && is_in_generator()) {
|
||||
// Ecma-262, 12.1.1 Static Semantics: Early Errors
|
||||
token_error(S.prev, "SyntaxError: Yield cannot be used as label inside generators");
|
||||
token_error(S.prev, "Yield cannot be used as label inside generators");
|
||||
}
|
||||
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
||||
// ECMA-262, 12.12: An ECMAScript program is considered
|
||||
// syntactically incorrect if it contains a
|
||||
// LabelledStatement that is enclosed by a
|
||||
// LabelledStatement with the same Identifier as label.
|
||||
croak("SyntaxError: Label " + label.name + " defined twice");
|
||||
croak("Label " + label.name + " defined twice");
|
||||
}
|
||||
expect(":");
|
||||
S.labels.push(label);
|
||||
@@ -1135,7 +1134,7 @@ function parse($TEXT, options) {
|
||||
label.references.forEach(function(ref){
|
||||
if (ref instanceof AST_Continue) {
|
||||
ref = ref.label.start;
|
||||
croak("SyntaxError: Continue label `" + label.name + "` refers to non-IterationStatement.",
|
||||
croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
|
||||
ref.line, ref.col, ref.pos);
|
||||
}
|
||||
});
|
||||
@@ -1155,11 +1154,11 @@ function parse($TEXT, options) {
|
||||
if (label != null) {
|
||||
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
||||
if (!ldef)
|
||||
croak("SyntaxError: Undefined label " + label.name);
|
||||
croak("Undefined label " + label.name);
|
||||
label.thedef = ldef;
|
||||
}
|
||||
else if (S.in_loop == 0)
|
||||
croak("SyntaxError: " + type.TYPE + " not inside a loop or switch");
|
||||
croak(type.TYPE + " not inside a loop or switch");
|
||||
semicolon();
|
||||
var stat = new type({ label: label });
|
||||
if (ldef) ldef.references.push(stat);
|
||||
@@ -1180,7 +1179,7 @@ function parse($TEXT, options) {
|
||||
if (is_in || is_of) {
|
||||
if ((init instanceof AST_Definitions) &&
|
||||
init.definitions.length > 1)
|
||||
croak("SyntaxError: Only one variable declaration allowed in for..in loop");
|
||||
croak("Only one variable declaration allowed in for..in loop");
|
||||
next();
|
||||
if (is_in) {
|
||||
return for_in(init);
|
||||
@@ -1232,7 +1231,7 @@ function parse($TEXT, options) {
|
||||
|
||||
var arrow_function = function(args) {
|
||||
if (S.token.nlb) {
|
||||
croak("SyntaxError: Unexpected newline before arrow (=>)");
|
||||
croak("Unexpected newline before arrow (=>)");
|
||||
}
|
||||
|
||||
expect_token("arrow", "=>");
|
||||
@@ -1302,7 +1301,7 @@ function parse($TEXT, options) {
|
||||
case "eval":
|
||||
case "yield":
|
||||
if (strict_mode) {
|
||||
token_error(token, "SyntaxError: Unexpected " + token.value + " identifier as parameter inside strict mode");
|
||||
token_error(token, "Unexpected " + token.value + " identifier as parameter inside strict mode");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1331,7 +1330,7 @@ function parse($TEXT, options) {
|
||||
},
|
||||
check_strict: function() {
|
||||
if (tracker.is_strict() && duplicate !== false) {
|
||||
token_error(duplicate, "SyntaxError: Parameter " + duplicate.value + " was used already");
|
||||
token_error(duplicate, "Parameter " + duplicate.value + " was used already");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1457,7 +1456,7 @@ function parse($TEXT, options) {
|
||||
}));
|
||||
next();
|
||||
} else {
|
||||
croak("SyntaxError: Invalid function parameter");
|
||||
croak("Invalid function parameter");
|
||||
}
|
||||
if (is("operator", "=") && is_expand === false) {
|
||||
used_parameters.mark_default_assignment(S.token);
|
||||
@@ -1568,7 +1567,7 @@ function parse($TEXT, options) {
|
||||
end: prev()
|
||||
});
|
||||
} else {
|
||||
croak("SyntaxError: Invalid function parameter");
|
||||
croak("Invalid function parameter");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,7 +1630,7 @@ function parse($TEXT, options) {
|
||||
function _yield_expression() {
|
||||
// Previous token must be keyword yield and not be interpret as an identifier
|
||||
if (!is_in_generator()) {
|
||||
croak("SyntaxError: Unexpected yield expression outside generator function",
|
||||
croak("Unexpected yield expression outside generator function",
|
||||
S.prev.line, S.prev.col, S.prev.pos);
|
||||
}
|
||||
var star = false;
|
||||
@@ -1747,7 +1746,7 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
if (!bcatch && !bfinally)
|
||||
croak("SyntaxError: Missing catch/finally blocks");
|
||||
croak("Missing catch/finally blocks");
|
||||
return new AST_Try({
|
||||
body : body,
|
||||
bcatch : bcatch,
|
||||
@@ -1872,7 +1871,7 @@ function parse($TEXT, options) {
|
||||
break;
|
||||
case "operator":
|
||||
if (!is_identifier_string(tok.value)) {
|
||||
croak("SyntaxError: Invalid getter/setter name: " + tok.value,
|
||||
croak("Invalid getter/setter name: " + tok.value,
|
||||
tok.line, tok.col, tok.pos);
|
||||
}
|
||||
ret = _make_symbol(AST_SymbolRef);
|
||||
@@ -1985,6 +1984,10 @@ function parse($TEXT, options) {
|
||||
});
|
||||
});
|
||||
|
||||
var create_accessor = embed_tokens(function() {
|
||||
return function_(AST_Accessor);
|
||||
});
|
||||
|
||||
var object_or_object_destructuring_ = embed_tokens(function() {
|
||||
var start = S.token, first = true, a = [];
|
||||
expect("{");
|
||||
@@ -2142,7 +2145,7 @@ function parse($TEXT, options) {
|
||||
key : name,
|
||||
quote : name instanceof AST_SymbolMethod ?
|
||||
property_token.quote : undefined,
|
||||
value : function_(AST_Accessor),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
@@ -2156,7 +2159,7 @@ function parse($TEXT, options) {
|
||||
key : name,
|
||||
quote : name instanceof AST_SymbolMethod ?
|
||||
property_token.quote : undefined,
|
||||
value : function_(AST_Accessor),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
@@ -2286,7 +2289,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
case "name":
|
||||
if (tmp.value === "yield" && S.input.has_directive("use strict") && !is_in_generator()) {
|
||||
token_error(tmp, "SyntaxError: Unexpected yield identifier inside strict mode");
|
||||
token_error(tmp, "Unexpected yield identifier inside strict mode");
|
||||
}
|
||||
case "string":
|
||||
case "num":
|
||||
@@ -2325,11 +2328,11 @@ function parse($TEXT, options) {
|
||||
|
||||
function as_symbol(type, noerror) {
|
||||
if (!is("name")) {
|
||||
if (!noerror) croak("SyntaxError: Name expected");
|
||||
if (!noerror) croak("Name expected");
|
||||
return null;
|
||||
}
|
||||
if (is("name", "yield") && S.input.has_directive("use strict")) {
|
||||
token_error(S.prev, "SyntaxError: Unexpected yield identifier inside strict mode");
|
||||
token_error(S.prev, "Unexpected yield identifier inside strict mode");
|
||||
}
|
||||
var sym = _make_symbol(type);
|
||||
next();
|
||||
@@ -2418,7 +2421,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function make_unary(ctor, op, expr) {
|
||||
if ((op == "++" || op == "--") && !is_assignable(expr))
|
||||
croak("SyntaxError: Invalid use of " + op + " operator");
|
||||
croak("Invalid use of " + op + " operator");
|
||||
return new ctor({ operator: op, expression: expr });
|
||||
};
|
||||
|
||||
@@ -2482,7 +2485,7 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return _yield_expression();
|
||||
} else if (S.input.has_directive("use strict")) {
|
||||
token_error(S.token, "SyntaxError: Unexpected yield identifier inside strict mode")
|
||||
token_error(S.token, "Unexpected yield identifier inside strict mode")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2525,7 +2528,7 @@ function parse($TEXT, options) {
|
||||
// Only allow expansion as last element
|
||||
if (node.elements[i] instanceof AST_Expansion) {
|
||||
if (i + 1 !== node.elements.length) {
|
||||
token_error(node.elements[i].start, "SyntaxError: Spread must the be last element in destructuring array");
|
||||
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
|
||||
}
|
||||
node.elements[i].expression = walk(node.elements[i].expression);
|
||||
}
|
||||
@@ -2565,7 +2568,7 @@ function parse($TEXT, options) {
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
croak("SyntaxError: Invalid assignment");
|
||||
croak("Invalid assignment");
|
||||
}
|
||||
return left;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user