support nullish coalescing operator (#4678)
This commit is contained in:
@@ -85,7 +85,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
1 - single
|
1 - single
|
||||||
2 - double
|
2 - double
|
||||||
3 - original
|
3 - original
|
||||||
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
`wrap_iife` Wrap IIFEs in parentheses. Note: you may
|
||||||
want to disable `negate_iife` under
|
want to disable `negate_iife` under
|
||||||
compressor options.
|
compressor options.
|
||||||
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
|
-O, --output-opts [options] Specify output options (`beautify` disabled by default).
|
||||||
|
|||||||
@@ -2182,6 +2182,7 @@ merge(Compressor.prototype, {
|
|||||||
var lazy = lazy_op[expr.operator];
|
var lazy = lazy_op[expr.operator];
|
||||||
if (unused
|
if (unused
|
||||||
&& lazy
|
&& lazy
|
||||||
|
&& expr.operator != "??"
|
||||||
&& expr.right instanceof AST_Assign
|
&& expr.right instanceof AST_Assign
|
||||||
&& expr.right.operator == "="
|
&& expr.right.operator == "="
|
||||||
&& !(expr.right.left instanceof AST_Destructured)) {
|
&& !(expr.right.left instanceof AST_Destructured)) {
|
||||||
@@ -3840,7 +3841,7 @@ merge(Compressor.prototype, {
|
|||||||
node.DEFMETHOD("is_string", func);
|
node.DEFMETHOD("is_string", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
var lazy_op = makePredicate("&& ||");
|
var lazy_op = makePredicate("&& || ??");
|
||||||
|
|
||||||
(function(def) {
|
(function(def) {
|
||||||
function to_node(value, orig) {
|
function to_node(value, orig) {
|
||||||
@@ -4286,6 +4287,9 @@ merge(Compressor.prototype, {
|
|||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case "&&" : result = left && right; break;
|
case "&&" : result = left && right; break;
|
||||||
case "||" : result = left || right; break;
|
case "||" : result = left || right; break;
|
||||||
|
case "??" :
|
||||||
|
result = left == null ? right : left;
|
||||||
|
break;
|
||||||
case "|" : result = left | right; break;
|
case "|" : result = left | right; break;
|
||||||
case "&" : result = left & right; break;
|
case "&" : result = left & right; break;
|
||||||
case "^" : result = left ^ right; break;
|
case "^" : result = left ^ right; break;
|
||||||
@@ -7130,6 +7134,7 @@ merge(Compressor.prototype, {
|
|||||||
node = this.clone();
|
node = this.clone();
|
||||||
node.right = right.drop_side_effect_free(compressor);
|
node.right = right.drop_side_effect_free(compressor);
|
||||||
}
|
}
|
||||||
|
if (this.operator == "??") return node;
|
||||||
return (first_in_statement ? best_of_statement : best_of_expression)(node, make_node(AST_Binary, this, {
|
return (first_in_statement ? best_of_statement : best_of_expression)(node, make_node(AST_Binary, this, {
|
||||||
operator: node.operator == "&&" ? "||" : "&&",
|
operator: node.operator == "&&" ? "||" : "&&",
|
||||||
left: node.left.negate(compressor, first_in_statement),
|
left: node.left.negate(compressor, first_in_statement),
|
||||||
@@ -9159,7 +9164,7 @@ merge(Compressor.prototype, {
|
|||||||
// (a = b, x || a = c) ---> a = x ? b : c
|
// (a = b, x || a = c) ---> a = x ? b : c
|
||||||
function to_conditional_assignment(compressor, def, value, node) {
|
function to_conditional_assignment(compressor, def, value, node) {
|
||||||
if (!(node instanceof AST_Binary)) return;
|
if (!(node instanceof AST_Binary)) return;
|
||||||
if (!lazy_op[node.operator]) return;
|
if (!(node.operator == "&&" || node.operator == "||")) return;
|
||||||
if (!(node.right instanceof AST_Assign)) return;
|
if (!(node.right instanceof AST_Assign)) return;
|
||||||
if (node.right.operator != "=") return;
|
if (node.right.operator != "=") return;
|
||||||
if (!(node.right.left instanceof AST_SymbolRef)) return;
|
if (!(node.right.left instanceof AST_SymbolRef)) return;
|
||||||
@@ -9680,22 +9685,41 @@ merge(Compressor.prototype, {
|
|||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "??":
|
||||||
|
var nullish = true;
|
||||||
case "||":
|
case "||":
|
||||||
var ll = fuzzy_eval(self.left);
|
var ll = fuzzy_eval(self.left, nullish);
|
||||||
if (!ll) {
|
if (nullish ? ll == null : !ll) {
|
||||||
AST_Node.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Condition left of {operator} always {value} [{file}:{line},{col}]", {
|
||||||
|
operator: self.operator,
|
||||||
|
value: nullish ? "nulish" : "false",
|
||||||
|
file: self.start.file,
|
||||||
|
line: self.start.line,
|
||||||
|
col: self.start.col,
|
||||||
|
});
|
||||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||||
} else if (!(ll instanceof AST_Node)) {
|
} else if (!(ll instanceof AST_Node)) {
|
||||||
AST_Node.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Condition left of {operator} always {value} [{file}:{line},{col}]", {
|
||||||
|
operator: self.operator,
|
||||||
|
value: nullish ? "defined" : "true",
|
||||||
|
file: self.start.file,
|
||||||
|
line: self.start.line,
|
||||||
|
col: self.start.col,
|
||||||
|
});
|
||||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||||
}
|
}
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if (!rr) {
|
if (!rr) {
|
||||||
if (in_bool || parent.operator == "||" && parent.left === compressor.self()) {
|
if (in_bool || parent.operator == "||" && parent.left === compressor.self()) {
|
||||||
AST_Node.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Dropping side-effect-free {operator} [{file}:{line},{col}]", {
|
||||||
|
operator: self.operator,
|
||||||
|
file: self.start.file,
|
||||||
|
line: self.start.line,
|
||||||
|
col: self.start.col,
|
||||||
|
});
|
||||||
return self.left.optimize(compressor);
|
return self.left.optimize(compressor);
|
||||||
}
|
}
|
||||||
} else if (!(rr instanceof AST_Node)) {
|
} else if (!nullish && !(rr instanceof AST_Node)) {
|
||||||
if (in_bool) {
|
if (in_bool) {
|
||||||
AST_Node.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
||||||
return make_sequence(self, [
|
return make_sequence(self, [
|
||||||
@@ -9705,7 +9729,7 @@ merge(Compressor.prototype, {
|
|||||||
} else self.truthy = true;
|
} else self.truthy = true;
|
||||||
}
|
}
|
||||||
// x && true || y ---> x ? true : y
|
// x && true || y ---> x ? true : y
|
||||||
if (self.left.operator == "&&") {
|
if (!nullish && self.left.operator == "&&") {
|
||||||
var lr = self.left.right.is_truthy() || self.left.right.evaluate(compressor, true);
|
var lr = self.left.right.is_truthy() || self.left.right.evaluate(compressor, true);
|
||||||
if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
|
if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
|
||||||
condition: self.left.left,
|
condition: self.left.left,
|
||||||
@@ -10047,9 +10071,9 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function fuzzy_eval(node) {
|
function fuzzy_eval(node, nullish) {
|
||||||
if (node.truthy) return true;
|
if (node.truthy) return true;
|
||||||
if (node.falsy) return false;
|
if (node.falsy && !nullish) return false;
|
||||||
if (node.is_truthy()) return true;
|
if (node.is_truthy()) return true;
|
||||||
return node.evaluate(compressor, true);
|
return node.evaluate(compressor, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -753,7 +753,9 @@ function OutputStream(options) {
|
|||||||
if (p instanceof AST_Binary) {
|
if (p instanceof AST_Binary) {
|
||||||
var po = p.operator, pp = PRECEDENCE[po];
|
var po = p.operator, pp = PRECEDENCE[po];
|
||||||
var so = this.operator, sp = PRECEDENCE[so];
|
var so = this.operator, sp = PRECEDENCE[so];
|
||||||
return pp > sp || (pp == sp && this === p[po == "**" ? "left" : "right"]);
|
return pp > sp
|
||||||
|
|| po == "??" && (so == "&&" || so == "||")
|
||||||
|
|| (pp == sp && this === p[po == "**" ? "left" : "right"]);
|
||||||
}
|
}
|
||||||
// (foo && bar)()
|
// (foo && bar)()
|
||||||
if (p instanceof AST_Call) return p.expression === this;
|
if (p instanceof AST_Call) return p.expression === this;
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ var OPERATORS = makePredicate([
|
|||||||
"^=",
|
"^=",
|
||||||
"&=",
|
"&=",
|
||||||
"&&",
|
"&&",
|
||||||
"||"
|
"||",
|
||||||
|
"??",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var NEWLINE_CHARS = "\n\r\u2028\u2029";
|
var NEWLINE_CHARS = "\n\r\u2028\u2029";
|
||||||
@@ -662,6 +663,7 @@ var PRECEDENCE = function(a, ret) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}([
|
}([
|
||||||
|
["??"],
|
||||||
["||"],
|
["||"],
|
||||||
["&&"],
|
["&&"],
|
||||||
["|"],
|
["|"],
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ destructured_funarg: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
await_parenthesis: {
|
await_parentheses: {
|
||||||
input: {
|
input: {
|
||||||
async function f() {
|
async function f() {
|
||||||
await (a => a);
|
await (a => a);
|
||||||
@@ -43,7 +43,7 @@ await_parenthesis: {
|
|||||||
expect_exact: "async function f(){await(a=>a)}"
|
expect_exact: "async function f(){await(a=>a)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_parenthesis_init: {
|
for_parentheses_init: {
|
||||||
input: {
|
input: {
|
||||||
for (a => (a in a); console.log(42););
|
for (a => (a in a); console.log(42););
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ for_parenthesis_init: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_parenthesis_condition: {
|
for_parentheses_condition: {
|
||||||
input: {
|
input: {
|
||||||
for (console.log(42); a => (a in a);)
|
for (console.log(42); a => (a in a);)
|
||||||
break;
|
break;
|
||||||
@@ -62,7 +62,7 @@ for_parenthesis_condition: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_parenthesis_step: {
|
for_parentheses_step: {
|
||||||
input: {
|
input: {
|
||||||
for (; console.log(42); a => (a in a));
|
for (; console.log(42); a => (a in a));
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ for_parenthesis_step: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_assign_parenthesis_init: {
|
for_assign_parentheses_init: {
|
||||||
input: {
|
input: {
|
||||||
for (f = a => (a in a); console.log(42););
|
for (f = a => (a in a); console.log(42););
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ for_assign_parenthesis_init: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_assign_parenthesis_condition: {
|
for_assign_parentheses_condition: {
|
||||||
input: {
|
input: {
|
||||||
for (console.log(42); f = a => (a in a);)
|
for (console.log(42); f = a => (a in a);)
|
||||||
break;
|
break;
|
||||||
@@ -90,7 +90,7 @@ for_assign_parenthesis_condition: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_assign_parenthesis_step: {
|
for_assign_parentheses_step: {
|
||||||
input: {
|
input: {
|
||||||
for (; console.log(42); f = a => (a in a));
|
for (; console.log(42); f = a => (a in a));
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ for_assign_parenthesis_step: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_declaration_parenthesis_init: {
|
for_declaration_parentheses_init: {
|
||||||
input: {
|
input: {
|
||||||
for (var f = a => (a in a); console.log(42););
|
for (var f = a => (a in a); console.log(42););
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ for_declaration_parenthesis_init: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
for_statement_parenthesis_init: {
|
for_statement_parentheses_init: {
|
||||||
input: {
|
input: {
|
||||||
for (a => {
|
for (a => {
|
||||||
a in a;
|
a in a;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ yield: {
|
|||||||
node_version: ">=12"
|
node_version: ">=12"
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional_parenthesis: {
|
conditional_parentheses: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ defaults: {
|
|||||||
expect_exact: "export default 42;export default async;export default(x,y)=>x*x;export default class{}export default function*(a,b){}export default async function f({c:c},...[d]){}"
|
expect_exact: "export default 42;export default async;export default(x,y)=>x*x;export default class{}export default function*(a,b){}export default async function f({c:c},...[d]){}"
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults_parenthesis_1: {
|
defaults_parentheses_1: {
|
||||||
input: {
|
input: {
|
||||||
export default function() {
|
export default function() {
|
||||||
console.log("FAIL");
|
console.log("FAIL");
|
||||||
@@ -47,7 +47,7 @@ defaults_parenthesis_1: {
|
|||||||
expect_exact: 'export default function(){console.log("FAIL")}console.log("PASS");'
|
expect_exact: 'export default function(){console.log("FAIL")}console.log("PASS");'
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults_parenthesis_2: {
|
defaults_parentheses_2: {
|
||||||
input: {
|
input: {
|
||||||
export default (async function() {
|
export default (async function() {
|
||||||
console.log("PASS");
|
console.log("PASS");
|
||||||
|
|||||||
@@ -2053,7 +2053,7 @@ issue_2898: {
|
|||||||
expect_stdout: "2"
|
expect_stdout: "2"
|
||||||
}
|
}
|
||||||
|
|
||||||
deduplicate_parenthesis: {
|
deduplicate_parentheses: {
|
||||||
input: {
|
input: {
|
||||||
({}).a = b;
|
({}).a = b;
|
||||||
(({}).a = b)();
|
(({}).a = b)();
|
||||||
|
|||||||
@@ -501,14 +501,14 @@ do_switch: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in_parenthesis_1: {
|
in_parentheses_1: {
|
||||||
input: {
|
input: {
|
||||||
for (("foo" in {});0;);
|
for (("foo" in {});0;);
|
||||||
}
|
}
|
||||||
expect_exact: 'for(("foo"in{});0;);'
|
expect_exact: 'for(("foo"in{});0;);'
|
||||||
}
|
}
|
||||||
|
|
||||||
in_parenthesis_2: {
|
in_parentheses_2: {
|
||||||
input: {
|
input: {
|
||||||
for ((function(){ "foo" in {}; });0;);
|
for ((function(){ "foo" in {}; });0;);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ new_with_unary_prefix: {
|
|||||||
expect_exact: 'var bar=(+new Date).toString(32);';
|
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||||
}
|
}
|
||||||
|
|
||||||
dot_parenthesis_1: {
|
dot_parentheses_1: {
|
||||||
input: {
|
input: {
|
||||||
console.log(new (Math.random().constructor) instanceof Number);
|
console.log(new (Math.random().constructor) instanceof Number);
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ dot_parenthesis_1: {
|
|||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
dot_parenthesis_2: {
|
dot_parentheses_2: {
|
||||||
input: {
|
input: {
|
||||||
console.log(typeof new function(){Math.random()}.constructor);
|
console.log(typeof new function(){Math.random()}.constructor);
|
||||||
}
|
}
|
||||||
|
|||||||
111
test/compress/nullish.js
Normal file
111
test/compress/nullish.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
parentheses: {
|
||||||
|
input: {
|
||||||
|
(console.log("foo") || console.log("bar") ?? console.log("baz")) && console.log("moo");
|
||||||
|
}
|
||||||
|
expect_exact:'((console.log("foo")||console.log("bar"))??console.log("baz"))&&console.log("moo");'
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
void console.log("foo" ?? "bar") ?? console.log("baz");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("baz");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignment_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
b ?? (a = "FAIL");
|
||||||
|
return a;
|
||||||
|
}("PASS", !console));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
b ?? (a = "FAIL");
|
||||||
|
return a;
|
||||||
|
}("PASS", !console));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignment_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = false;
|
||||||
|
a = "PASS",
|
||||||
|
b ?? (a = "FAIL"),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = false;
|
||||||
|
a = "PASS",
|
||||||
|
b ?? (a = "FAIL"),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignment_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = false;
|
||||||
|
a = "PASS",
|
||||||
|
b ?? (a = "FAIL"),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = false, a = "PASS";
|
||||||
|
b ?? (a = "FAIL"),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_assignment_4: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
!console ?? (a = "FAIL");
|
||||||
|
return a;
|
||||||
|
}("PASS"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
!console ?? (a = "FAIL");
|
||||||
|
return a;
|
||||||
|
}("PASS"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
@@ -777,7 +777,7 @@ issue_1710: {
|
|||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unary_binary_parenthesis: {
|
unary_binary_parentheses: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ tagged_chain: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_parenthesis_arrow: {
|
tag_parentheses_arrow: {
|
||||||
input: {
|
input: {
|
||||||
console.log((s => s.raw[0])`\tPASS`.slice(2));
|
console.log((s => s.raw[0])`\tPASS`.slice(2));
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ tag_parenthesis_arrow: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_parenthesis_new: {
|
tag_parentheses_new: {
|
||||||
input: {
|
input: {
|
||||||
(new function() {
|
(new function() {
|
||||||
return console.log;
|
return console.log;
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ describe("comments", function() {
|
|||||||
assert.strictEqual(result.code, code);
|
assert.strictEqual(result.code, code);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should handle comments around parenthesis correctly", function() {
|
it("Should handle comments around parentheses correctly", function() {
|
||||||
var code = [
|
var code = [
|
||||||
"a();",
|
"a();",
|
||||||
"/* foo */",
|
"/* foo */",
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ describe("parentheses", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should compress leading parenthesis with reasonable performance", function() {
|
it("Should compress leading parentheses with reasonable performance", function() {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
var code = [
|
var code = [
|
||||||
"({}?0:1)&&x();",
|
"({}?0:1)&&x();",
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ var SUPPORT = function(matrix) {
|
|||||||
for_of: "for (var a of []);",
|
for_of: "for (var a of []);",
|
||||||
generator: "function* f(){}",
|
generator: "function* f(){}",
|
||||||
let: "let a;",
|
let: "let a;",
|
||||||
|
nullish: "0 ?? 0",
|
||||||
rest: "var [...a] = [];",
|
rest: "var [...a] = [];",
|
||||||
rest_object: "var {...a} = {};",
|
rest_object: "var {...a} = {};",
|
||||||
spread: "[...[]];",
|
spread: "[...[]];",
|
||||||
@@ -231,6 +232,7 @@ var BINARY_OPS = [
|
|||||||
",",
|
",",
|
||||||
];
|
];
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
if (SUPPORT.nullish) BINARY_OPS.push("??");
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
if (SUPPORT.exponentiation) BINARY_OPS.push("**");
|
if (SUPPORT.exponentiation) BINARY_OPS.push("**");
|
||||||
|
|||||||
Reference in New Issue
Block a user