Skip to content

Commit

Permalink
Merge branch 'master' into feature/codeql
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-ivanov committed Apr 3, 2024
2 parents e4efcc2 + 0e04a22 commit 4a85809
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 37 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## v5.30.2
- Avoid optimizations inside computed keys, because they can cause js-engine-specific bugs.

## v5.30.1
- Removed useless `\` escapes for non-ascii characters
- Make modern identifier characters quoted for older environments (#1512)
Expand Down
55 changes: 48 additions & 7 deletions lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -1072,25 +1072,66 @@ function OutputStream(options) {
return true;
// this deals with precedence: 3 * (2 + 1)
if (p instanceof AST_Binary) {
const po = p.operator;
const so = this.operator;
const parent_op = p.operator;
const op = this.operator;

if (so === "??" && (po === "||" || po === "&&")) {
// It is forbidden for ?? to be used with || or && without parens.
if (op === "??" && (parent_op === "||" || parent_op === "&&")) {
return true;
}
if (parent_op === "??" && (op === "||" || op === "&&")) {
return true;
}

if (po === "??" && (so === "||" || so === "&&")) {
const pp = PRECEDENCE[parent_op];
const sp = PRECEDENCE[op];
if (pp > sp
|| (pp == sp
&& (this === p.right || parent_op == "**"))) {
return true;
}
}
if (p instanceof AST_PrivateIn) {
const op = this.operator;

const pp = PRECEDENCE["in"];
const sp = PRECEDENCE[op];
if (pp > sp || (pp == sp && this === p.value)) {
return true;
}
}
});

PARENS(AST_PrivateIn, function(output) {
var p = output.parent();
// (#x in this)()
if (p instanceof AST_Call && p.expression === this) {
return true;
}
// typeof (#x in this)
if (p instanceof AST_Unary) {
return true;
}
// (#x in this)["prop"], (#x in this).prop
if (p instanceof AST_PropAccess && p.expression === this) {
return true;
}
// same precedence as regular in operator
if (p instanceof AST_Binary) {
const parent_op = p.operator;

const pp = PRECEDENCE[po];
const sp = PRECEDENCE[so];
const pp = PRECEDENCE[parent_op];
const sp = PRECEDENCE["in"];
if (pp > sp
|| (pp == sp
&& (this === p.right || po == "**"))) {
&& (this === p.right || parent_op == "**"))) {
return true;
}
}
// rules are the same as binary in, but the class differs
if (p instanceof AST_PrivateIn && this === p.value) {
return true;
}
});

PARENS(AST_Yield, function(output) {
Expand Down
55 changes: 28 additions & 27 deletions lib/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -1027,9 +1027,8 @@ var LOGICAL_ASSIGNMENT = makePredicate([ "??=", "&&=", "||=" ]);

var PRECEDENCE = (function(a, ret) {
for (var i = 0; i < a.length; ++i) {
var b = a[i];
for (var j = 0; j < b.length; ++j) {
ret[b[j]] = i + 1;
for (const op of a[i]) {
ret[op] = i + 1;
}
}
return ret;
Expand Down Expand Up @@ -2381,29 +2380,6 @@ function parse($TEXT, options) {
if (is("template_head")) {
return subscripts(template_string(), allow_calls);
}
if (is("privatename")) {
if(!S.in_class) {
croak("Private field must be used in an enclosing class");
}

const start = S.token;
const key = new AST_SymbolPrivateProperty({
start,
name: start.value,
end: start
});
next();
expect_token("operator", "in");

const private_in = new AST_PrivateIn({
start,
key,
value: subscripts(as_atom_node(), allow_calls),
end: prev()
});

return subscripts(private_in, allow_calls);
}
if (ATOMIC_START_TOKEN.has(S.token.type)) {
return subscripts(as_atom_node(), allow_calls);
}
Expand Down Expand Up @@ -3316,7 +3292,32 @@ function parse($TEXT, options) {
};

function expr_ops(no_in) {
return expr_op(maybe_unary(true, true), 0, no_in);
// maybe_unary won't return us a AST_SymbolPrivateProperty
if (!no_in && is("privatename")) {
if(!S.in_class) {
croak("Private field must be used in an enclosing class");
}

const start = S.token;
const key = new AST_SymbolPrivateProperty({
start,
name: start.value,
end: start
});
next();
expect_token("operator", "in");

const private_in = new AST_PrivateIn({
start,
key,
value: expr_op(maybe_unary(true), PRECEDENCE["in"], no_in),
end: prev()
});

return expr_op(private_in, 0, no_in);
} else {
return expr_op(maybe_unary(true, true), 0, no_in);
}
}

var maybe_conditional = function(no_in) {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"homepage": "https://terser.org",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "5.30.1",
"version": "5.30.2",
"engines": {
"node": ">=10"
},
Expand Down
122 changes: 122 additions & 0 deletions test/compress/class-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,125 @@ allow_subscript_private_field: {
"PASS"
]
}

parens_in: {
input: {
class X {
static {
console.log(!(#x in this));
}
}
}
expect_exact: "class X{static{console.log(!(#x in this))}}"
}

parens_in_2: {
input: {
class X {
static {
console.log((#x in this) + 1);
}
}
}
expect_exact: "class X{static{console.log((#x in this)+1)}}"
}

parens_in_3: {
input: {
class X {
static {
console.log(#x in (this + 1));
}
}
}
expect_exact: "class X{static{console.log(#x in this+1)}}"
}

parens_in_4: {
input: {
class X {
static {
console.log(#x in this + 1);
}
}
}
expect_exact: "class X{static{console.log(#x in this+1)}}"
}

parens_in_5: {
input: {
class X {
static {
console.log((#x in this) | 1);
}
}
}
expect_exact: "class X{static{console.log(#x in this|1)}}"
}

parens_in_6: {
input: {
class X {
static {
console.log(#x in (this | 1));
}
}
}
expect_exact: "class X{static{console.log(#x in(this|1))}}"
}

parens_in_7: {
input: {
class X {
static {
console.log(#x in this | 1);
}
}
}
expect_exact: "class X{static{console.log(#x in this|1)}}"
}

parens_in_8: {
input: {
class X {
static {
console.log((#x in this) in this);
}
}
}
expect_exact: "class X{static{console.log(#x in this in this)}}"
}

parens_in_9: {
input: {
class X {
static {
console.log(#x in (this in this));
}
}
}
expect_exact: "class X{static{console.log(#x in(this in this))}}"
}

parens_in_10: {
input: {
class X {
static {
console.log(#x in this in this);
}
}
}
expect_exact: "class X{static{console.log(#x in this in this)}}"
}

parens_in_11: {
input: {
class X {
static {
console.log(this in (#x in this));
}
}
}
expect_exact: "class X{static{console.log(this in(#x in this))}}"
}

0 comments on commit 4a85809

Please sign in to comment.