feat: backport bigint support to uglify-es from #4583
This commit is contained in:
parent
569757d14d
commit
fd35571f37
18
lib/ast.js
18
lib/ast.js
|
|
@ -1068,7 +1068,23 @@ var AST_Number = DEFNODE("Number", "value literal", {
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
value: "[number] the numeric value",
|
value: "[number] the numeric value",
|
||||||
literal: "[string] numeric value as string (optional)"
|
literal: "[string] numeric value as string (optional)"
|
||||||
}
|
},
|
||||||
|
_validate: function() {
|
||||||
|
if (typeof this.value != "number") throw new Error("value must be number");
|
||||||
|
if (!isFinite(this.value)) throw new Error("value must be finite");
|
||||||
|
if (this.value < 0) throw new Error("value cannot be negative");
|
||||||
|
},
|
||||||
|
}, AST_Constant);
|
||||||
|
|
||||||
|
var AST_BigInt = DEFNODE("BigInt", "value", {
|
||||||
|
$documentation: "A BigInt literal",
|
||||||
|
$propdoc: {
|
||||||
|
value: "[string] the numeric representation",
|
||||||
|
},
|
||||||
|
_validate: function() {
|
||||||
|
if (typeof this.value != "string") throw new Error("value must be string");
|
||||||
|
if (this.value[0] == "-") throw new Error("value cannot be negative");
|
||||||
|
},
|
||||||
}, AST_Constant);
|
}, AST_Constant);
|
||||||
|
|
||||||
var AST_RegExp = DEFNODE("RegExp", "value", {
|
var AST_RegExp = DEFNODE("RegExp", "value", {
|
||||||
|
|
|
||||||
|
|
@ -865,13 +865,11 @@ function OutputStream(options) {
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Number, function(output){
|
PARENS(AST_Number, function(output){
|
||||||
|
if (!output.option("galio")) return false;
|
||||||
|
// https://github.com/mishoo/UglifyJS/pull/1009
|
||||||
|
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_PropAccess && p.expression === this) {
|
return p instanceof AST_PropAccess && p.expression === this && /^0/.test(make_num(this.value));
|
||||||
var value = this.getValue();
|
|
||||||
if (value < 0 || /^0/.test(make_num(value))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Assign, AST_Conditional ], function(output){
|
PARENS([ AST_Assign, AST_Conditional ], function(output){
|
||||||
|
|
|
||||||
25
lib/parse.js
25
lib/parse.js
|
|
@ -377,9 +377,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function read_while(pred) {
|
function read_while(pred) {
|
||||||
var ret = "", ch, i = 0;
|
var ret = "", ch;
|
||||||
while ((ch = peek()) && pred(ch, i++))
|
while ((ch = peek()) && pred(ch)) ret += next();
|
||||||
ret += next();
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -389,7 +388,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||||
|
|
||||||
function read_num(prefix) {
|
function read_num(prefix) {
|
||||||
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
|
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
|
||||||
var num = read_while(function(ch, i){
|
var num = read_while(function(ch){
|
||||||
var code = ch.charCodeAt(0);
|
var code = ch.charCodeAt(0);
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 98: case 66: // bB
|
case 98: case 66: // bB
|
||||||
|
|
@ -399,9 +398,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||||
return has_x ? false : (has_x = true);
|
return has_x ? false : (has_x = true);
|
||||||
case 101: case 69: // eE
|
case 101: case 69: // eE
|
||||||
return has_x ? true : has_e ? false : (has_e = after_e = true);
|
return has_x ? true : has_e ? false : (has_e = after_e = true);
|
||||||
case 45: // -
|
case 43: case 45:
|
||||||
return after_e || (i == 0 && !prefix);
|
|
||||||
case 43: // +
|
|
||||||
return after_e;
|
return after_e;
|
||||||
case (after_e = false, 46): // .
|
case (after_e = false, 46): // .
|
||||||
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false;
|
||||||
|
|
@ -413,11 +410,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||||
parse_error("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);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) {
|
if (isNaN(valid)) parse_error("Invalid syntax: " + num);
|
||||||
return token("num", valid);
|
if (has_dot || has_e || peek() != "n") return token("num", valid);
|
||||||
} else {
|
return token("bigint", num.toLowerCase() + next());
|
||||||
parse_error("Invalid syntax: " + num);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function read_escaped_char(in_string) {
|
function read_escaped_char(in_string) {
|
||||||
|
|
@ -847,7 +842,7 @@ var PRECEDENCE = (function(a, ret){
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
|
var ATOMIC_START_TOKEN = makePredicate([ "atom", "bigint", "num", "string", "regexp", "name" ]);
|
||||||
|
|
||||||
/* -----[ Parser ]----- */
|
/* -----[ Parser ]----- */
|
||||||
|
|
||||||
|
|
@ -1003,6 +998,7 @@ function parse($TEXT, options) {
|
||||||
return dir ? new AST_Directive(stat.body) : stat;
|
return dir ? new AST_Directive(stat.body) : stat;
|
||||||
case "template_head":
|
case "template_head":
|
||||||
case "num":
|
case "num":
|
||||||
|
case "bigint":
|
||||||
case "regexp":
|
case "regexp":
|
||||||
case "operator":
|
case "operator":
|
||||||
case "atom":
|
case "atom":
|
||||||
|
|
@ -1935,6 +1931,9 @@ function parse($TEXT, options) {
|
||||||
case "num":
|
case "num":
|
||||||
ret = new AST_Number({ start: tok, end: tok, value: tok.value });
|
ret = new AST_Number({ start: tok, end: tok, value: tok.value });
|
||||||
break;
|
break;
|
||||||
|
case "bigint":
|
||||||
|
ret = new AST_BigInt({ start: tok, end: tok, value: tok.value });
|
||||||
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
ret = new AST_String({
|
ret = new AST_String({
|
||||||
start : tok,
|
start : tok,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ holes_and_undefined: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constant_join: {
|
constant_join_1: {
|
||||||
options = {
|
options = {
|
||||||
unsafe : true,
|
unsafe : true,
|
||||||
evaluate : true
|
evaluate : true
|
||||||
|
|
@ -37,7 +37,7 @@ constant_join: {
|
||||||
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||||
var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
|
var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
|
||||||
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
||||||
var e = [].join(foo + bar);
|
var e = (foo, bar, "");
|
||||||
var f = [].join("");
|
var f = [].join("");
|
||||||
var g = [].join("foo");
|
var g = [].join("foo");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
test/compress/bigint.js
Normal file
46
test/compress/bigint.js
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
arithmetic: {
|
||||||
|
input: {
|
||||||
|
console.log(((1n + 0x2n) * (0o3n - -4n)) >> (5n - 6n));
|
||||||
|
}
|
||||||
|
expect_exact: "console.log((1n+0x2n)*(0o3n- -4n)>>5n-6n);"
|
||||||
|
expect_stdout: "42n"
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
minus_dot: {
|
||||||
|
input: {
|
||||||
|
console.log(typeof -42n.toString(), typeof (-42n).toString());
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(typeof-42n.toString(),typeof(-42n).toString());"
|
||||||
|
expect_stdout: "number string"
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log((0xDEAD_BEEFn).toString(16));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(0xdeadbeefn.toString(16));
|
||||||
|
}
|
||||||
|
expect_stdout: "deadbeef"
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
||||||
|
Number: {
|
||||||
|
options = {
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Number(-0xfeed_dead_beef_badn));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(+("" + -0xfeed_dead_beef_badn));
|
||||||
|
}
|
||||||
|
expect_stdout: "-1148098955808013200"
|
||||||
|
node_version: ">=10"
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ issue_269_1: {
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
f(
|
f(
|
||||||
x + '', +x, !!x,
|
'' + x, +('' + x), !!x,
|
||||||
'', 0, false
|
'', 0, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ evaluate_3: {
|
||||||
console.log(1 + Number(x) + 2);
|
console.log(1 + Number(x) + 2);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(3 + +x);
|
console.log(+("" + x) + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user