Compare commits

...

4 Commits

Author SHA1 Message Date
Alex Lam S.L
4cbf5a7821 v2.8.26 2017-05-16 07:13:58 +08:00
Alex Lam S.L
93d4224072 Merge pull request #1947 from alexlamsl/v2.8.26 2017-05-16 07:12:28 +08:00
Alex Lam S.L
6cd580dc23 fix parsing of property access after new line (#1944)
Account for comments when detecting property access in `tokenizer`.

fixes #1943
2017-05-16 06:34:10 +08:00
Alex Lam S.L
ecb63ad8bc improve keyword-related parser errors (#1941)
fixes #1937
2017-05-16 06:33:57 +08:00
6 changed files with 270 additions and 176 deletions

View File

@@ -285,7 +285,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
prev_was_dot = (type == "punc" && value == ".");
if (type == "punc" && value == ".") {
prev_was_dot = true;
} else if (!is_comment) {
prev_was_dot = false;
}
var ret = {
type : type,
value : value,
@@ -803,17 +807,16 @@ function parse($TEXT, options) {
};
var statement = embed_tokens(function() {
var tmp;
handle_regexp();
switch (S.token.type) {
case "string":
if (S.in_directives) {
tmp = peek();
var token = peek();
if (S.token.raw.indexOf("\\") == -1
&& (tmp.nlb
|| is_token(tmp, "eof")
|| is_token(tmp, "punc", ";")
|| is_token(tmp, "punc", "}"))) {
&& (token.nlb
|| is_token(token, "eof")
|| is_token(token, "punc", ";")
|| is_token(token, "punc", "}"))) {
S.input.add_directive(S.token.value);
} else {
S.in_directives = false;
@@ -852,75 +855,103 @@ function parse($TEXT, options) {
}
case "keyword":
switch (tmp = S.token.value, next(), tmp) {
switch (S.token.value) {
case "break":
next();
return break_cont(AST_Break);
case "continue":
next();
return break_cont(AST_Continue);
case "debugger":
next();
semicolon();
return new AST_Debugger();
case "do":
next();
var body = in_loop(statement);
expect_token("keyword", "while");
var condition = parenthesised();
semicolon(true);
return new AST_Do({
body : in_loop(statement),
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(true), tmp)
body : body,
condition : condition
});
case "while":
next();
return new AST_While({
condition : parenthesised(),
body : in_loop(statement)
});
case "for":
next();
return for_();
case "function":
next();
return function_(AST_Defun);
case "if":
next();
return if_();
case "return":
if (S.in_function == 0 && !options.bare_returns)
croak("'return' outside of function");
next();
var value = null;
if (is("punc", ";")) {
next();
} else if (!can_insert_semicolon()) {
value = expression(true);
semicolon();
}
return new AST_Return({
value: ( is("punc", ";")
? (next(), null)
: can_insert_semicolon()
? null
: (tmp = expression(true), semicolon(), tmp) )
value: value
});
case "switch":
next();
return new AST_Switch({
expression : parenthesised(),
body : in_loop(switch_body_)
});
case "throw":
next();
if (S.token.nlb)
croak("Illegal newline after 'throw'");
var value = expression(true);
semicolon();
return new AST_Throw({
value: (tmp = expression(true), semicolon(), tmp)
value: value
});
case "try":
next();
return try_();
case "var":
return tmp = var_(), semicolon(), tmp;
next();
var node = var_();
semicolon();
return node;
case "const":
return tmp = const_(), semicolon(), tmp;
next();
var node = const_();
semicolon();
return node;
case "with":
if (S.input.has_directive("use strict")) {
croak("Strict mode may not include a with statement");
}
next();
return new AST_With({
expression : parenthesised(),
body : statement()

View File

@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "2.8.25",
"version": "2.8.26",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -0,0 +1,31 @@
operator: {
input: {
a. //comment
typeof
}
expect_exact: "a.typeof;"
}
name: {
input: {
a. //comment
b
}
expect_exact: "a.b;"
}
keyword: {
input: {
a. //comment
default
}
expect_exact: "a.default;"
}
atom: {
input: {
a. //comment
true
}
expect_exact: "a.true;"
}

View File

@@ -0,0 +1 @@
if (0) else 1;

View File

@@ -0,0 +1 @@
return 42;

View File

@@ -381,4 +381,34 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should throw syntax error (else)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/else.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/else.js:1,7",
"if (0) else 1;",
" ^",
"SyntaxError: Unexpected token: keyword (else)"
].join("\n"));
done();
});
});
it("Should throw syntax error (return)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/return.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/return.js:1,0",
"return 42;",
"^",
"SyntaxError: 'return' outside of function"
].join("\n"));
done();
});
});
});